#glimpse(suicides_data)

#summary(suicides_data)

# it can be seen that 5 columns have multiple missing values
# we omit these by running the code below

suicides_complete <- suicides_data[complete.cases(suicides_data),]

A. Questions

Introduction

For this analysis, data from 326 local authorities in England with information about suicides, personal well-being, unemployment, income, deprivation and population was considered. This report aims to determine the relationship between these explanatory factors and suicides. The importance of this report is therefore reflected in the fact that studying these relationships will lead to a better understanding of what exactly influences an individual to undergo suicidal thoughts. With better knowledge of this, we can address those influential factors in an attempt to mitigate the occurrence of suicidal incidences in the general population.

NB: where (*) appears, that plot/table/graph etc. was not included due to the page limit but is not central to the main analysis…refer to rmarkdown file for original output

Q1. To what extent are personal well-being, unemployment, income and deprivation associated with the number of suicides in England?

Fitted Curves for Respective Explanatory Variables Against Suicide Rate

The overall trend of each factor is shown in figure 1. It can be observed that living score (deprivation) and unemployment rate have a positive relationship with suicide rate whereas median income and worthwhile (wellbeing) have a negative relationship with same. More specificially, increases in deprivation and unemployment and decreases in income and personal wellbeing result in more persons committing suicide. We also recognise the relationships each of these factors have with each other and how they affect suicide rates jointly. For example, deprivation intuitively should be related to high unemployment rates and specifically low income and the combination of these factors, in turn would have a negative effect on ones wellbeing, ultimately leaving room for suicidal thoughts.

Q2. What are the regional differences in the number of suicides in England?

region_data <- suicides_complete %>% 
  group_by(region) %>%
  summarise(mean_suicides = mean(suicides),
            #max_suicides = max(suicides),
            #min_suicides = min(suicides),
            average_suicide_rate = ((sum(suicides)/sum(population))*1e5),
            total_suicides = sum(suicides),
            total_pop = sum(population))
region_data %>%  kable(digits = 2,
        caption = "Regional Suicides Summary Statistics",
        align="c") %>%  
  kable_styling(bootstrap_options = "striped", full_width = F)
Regional Suicides Summary Statistics
region mean_suicides average_suicide_rate total_suicides total_pop
East Midlands 10.03 8.21 331 4030457
East of England 13.42 10.05 577 5742271
London 20.62 7.49 660 8817347
North East 23.92 10.85 287 2644727
North West 17.49 9.40 682 7258627
South East 10.71 7.87 664 8433480
South West 17.65 9.90 459 4634080
West Midlands 17.13 8.77 514 5860706
Yorkshire and The Humber 28.70 10.64 574 5396431

Looking at the table above, we can infer that Yorkshire and The Humber, North East and East of England have the three highest suicide rates whereas London, South East and East Midlands have the three lowest. The average suicide rate among those living in the region of Yorkshire and The Humber was approximately 1.5 more than those living in London. Interestingly, the three regions with the highest suicide rates are situated in the North of the UK whereas the two lowest suicide rates originate from the South. We note that the difference is not particularly significant (as the pink intervals in the graphs below interlap) but in order to quantify the further quantify the effects we are investigating, we take the instance of high and low unemployment rates as a reference. If all regions were to have the same unemployment rate, the average suicide rate would be fairly similar across each region, as seen in the table (refer to figure 3). However, under a low unemployment rate of 2.0, we observe subtle changes in the suicide rates (most increases), but the relative shape of the graph is unchanged. A higher unemployment rate of 7.0 sees substantial changes with both the average suicide rate and relative shape of the graph. One interesting thing to note is that the regions who initially had the highest suicide rates are now among the lowest, inferring that other factors such as deprivation, especially in the case of regional concerns, also affect the average suicides rates.

Effect of Low Unemployment Rates on Regional Suicide Rates

Effect of High Unemployment Rates on Regional Suicide Rates

Q3. Are there any difference in suicides with regards to the North-South divide?

Marginalising the regions even further into North and South proves that there is a somewhat significant difference overall. At low unemployment rates and living scores the north tends to have more suicides but the difference is debatable as the intervals just barely overlap. At higher unemployment rates both regions see similar suicide rates (approx 0.5 difference between suicide rate), implying that this has significant influence over suicide rates in both regions. Likewise, at higher levels of deprivation, there is approximately 1.0 difference in the suicide rates between both regions. Thus, overall there is a difference in suicides with regards to the North-South divide, mostly owing to differences in unemployment rates and deprivation; in other words, the North sees higher unemployment rates and more deprivation when compared to the South. When we consider the traditional notions surrounding the North-South divide in England, this conclusion supports aspects regarding the socioeconomic makeup of these regions.

Effect of Unemployment and Deprivation on Regional Suicide Rates

B. Materials and Methods

Data

std_dev <- apply(suicides_complete[,-c(1,3)], 2, sd)  # omitting first and third columns from summary as they are characters
min_val <- apply(suicides_complete[,-c(1,3)], 2, min)
max_val <- apply(suicides_complete[,-c(1,3)], 2, max)
mean_val <- apply(suicides_complete[,-c(1,3)], 2, mean)
total_val <- apply(suicides_complete[,-c(1,3)], 2, sum)


data.frame(min=min_val, max=max_val, mean=mean_val,sd=std_dev, total = total_val) %>% 
  kable(digits = 2,
        caption = "Suicides Summary Statistics",
        align="c") %>%  
  kable_styling(bootstrap_options = "striped", full_width = F)

# 4748 suicides recorded in 2018

After creating a dataframe without missing values, we first investigate the relationship between population size and the number of suicides. Intuitively, it is usually assumed that the number of suicides increases with growing population size and this is indeed observed in this case, as there is a strong linear relationship seen in the plot below (*). However, this creates an issue in terms of our analysis, as we are required to determine the association of the other four factors with suicides. More specifically, since a great amount of the suicides can be explained by the population size, we see the need to hold population constant (assume it to be a value of 1) so that it is not estimated by our model. We implement this by creating two offsets: one in terms of log(population/100,000) and just population/100,000; these will be particularly useful when having to try different models further on.

pop_plot <- suicides_complete %>% 
  group_by(region) %>%
  ggplot(aes(x = population,y = suicides)) + geom_point() + geom_smooth(formula = y~x,method = lm) 
plot(pop_plot)

#region_plot <- pop_plot + facet_wrap(~region)

In order to visualise the data, we first plot a histogram of the frequency of the number of suicides, which demonstrates a strong positive skew as seen below (*). Hence, we should anticipate having to either fit a poisson generalised linear model or a transformed linear model in order to best model the data.

plotNormalHistogram(suicides_complete$suicides)

In order to implement further analysis, categorical variables are generated in terms of low, medium and high, with regards to income, wellbeing, unemployment and deprivation. We employ visualisation of correlations between the numerical variables (*). We note the high correlation between population and suicides as we also explained earlier. None of our other variables seem to have a particularly high correlation with suicides, however, some variables, such as income and unemployment, seem to display moderate correlation between each other. We note this as they may be an indication of interaction taking place.

suicides_complete <- suicides_complete %>% 
     mutate(income = cut_number(median_income,3)) %>% 
     mutate(income = fct_recode(income,
                                   .low = levels(income)[1], 
                                   .medium = levels(income)[2], 
                                   .high = levels(income)[3]))

suicides_complete <- suicides_complete %>% 
     mutate(deprivation = cut_number(living_score,3)) %>% 
     mutate(deprivation = fct_recode(deprivation,
                                   .low = levels(deprivation)[1], 
                                   .medium = levels(deprivation)[2], 
                                   .high = levels(deprivation)[3]))

suicides_complete <- suicides_complete %>% 
     mutate(wellbeing = cut_number(worthwhile,3)) %>% 
     mutate(wellbeing = fct_recode(wellbeing,
                                   .low = levels(wellbeing)[1], 
                                   .medium = levels(wellbeing)[2], 
                                   .high = levels(wellbeing)[3]))

suicides_complete <- suicides_complete %>% 
     mutate(unemployment = cut_number(unemployment_rate,3)) %>% 
     mutate(unemployment = fct_recode(unemployment,
                                   .low = levels(unemployment)[1], 
                                   .medium = levels(unemployment)[2], 
                                   .high = levels(unemployment)[3]))

suicides_complete <- suicides_complete %>% mutate(suicide_rate = suicides/population*1e5, os = (population/1e5), log_os = log(population/1e5))
kable(cor(suicides_complete[,-c(1,3,9,10,11,12)]),
      digits=2) %>%  
        kable_styling(bootstrap_options = "striped", full_width = F )
pairs(suicides_complete[,-c(1,3,9,10,11,12,13,14,15)])

Q1. To what extent are personal well-being, unemployment, income and deprivation associated with the number of suicides in England?

My first thought was to construct a simple linear model using the required variables to be estimated and the non-log offset (as this is a non-transformed model). This model resulted in an R-squared value of 0.334, however the plot of the actual values vs fitted values proved to be very poor. In order to improve on this, I decided it might be best to plot each explanatory variable against suicides and use LOESS smoothing to better visualise their relationship.

initial_model <- lm(suicides ~ unemployment_rate + worthwhile + median_income + living_score,  offset = os, data = suicides_complete)
ls_plot<-suicides_complete %>%
  ggplot(aes(living_score, suicides)) +
  geom_point() +
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 1, raw = T),
              se = F, aes(col = "blue")) +
  geom_smooth(se = T, aes(col = "red"), linetype ="dashed") +
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 2, raw = T),
              se = F, aes(col = "green")) +
  scale_color_identity(name = "Smooth Type", 
                       breaks = c("blue", "red", "green"),
                       labels = c("Linear", "LOESS","Quadratic"), guide = "legend")

ur_plot<-suicides_complete %>%
  ggplot(aes(unemployment_rate, suicides)) +
  geom_point() + 
  scale_x_continuous(trans = "log") +
  geom_smooth(method = lm, formula = y ~ poly(x,1),
              se = F, aes(col = "blue")) +
  geom_smooth(se = T, aes(col = "red"), linetype ="dashed") +
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 2, raw = T),
              se = F, aes(col = "green"))+ xlab("unemployment_rate(log)") +
  scale_color_identity(name = "Smooth Type", 
                       breaks = c("blue", "red", "green"),
                       labels = c("Linear", "LOESS","Quadratic"), guide = "legend")

mi_plot<-suicides_complete %>%
  ggplot(aes(median_income, suicides)) +
  geom_point() + 
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 1, raw = T),
              se = F, aes(col = "blue")) +
  geom_smooth(se = T, aes(col = "red"), linetype ="dashed") +
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 2, raw = T),
              se = F, aes(col = "green")) +
  scale_color_identity(name = "Smooth Type", 
                       breaks = c("blue", "red", "green"),
                       labels = c("Linear", "LOESS","Quadratic"), guide = "legend")

ww_plot<-suicides_complete %>%
  ggplot(aes(worthwhile, suicides)) +
  geom_point() + 
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 1, raw = T),
              se = F, aes(col = "blue")) +
  geom_smooth(se = T, aes(col = "red"), linetype ="dashed") +
  geom_smooth(method = lm, formula = y ~ poly(x, degree = 2, raw = T),
              se = F, aes(col = "green"))+
  scale_color_identity(name = "Smooth Type", 
                       breaks = c("blue", "red", "green"),
                       labels = c("Linear", "LOESS","Quadratic"), guide = "legend")



(ls_plot | ur_plot)/(ww_plot | mi_plot)

Figure 5: Smoothing

Along with LOESS smoothing, I also included linear and quadratic smoothing for ease of analysis. Firstly, it should be noted that unemployment_rate was log-transformed as it allowed for better linear smoothing; while the linear line slightly overestimates for higher unemployment rates, it still follows the general linear trend well and so we will consider this transformed variable in our model. Living_score can be seen to appear fairly cubic but this may just be possible due to extreme values (or outliers). Instead, we consider the linear trend which follows the LOESS line fairly consistently, only slightly underestimating at lower living scores and overestimating even less at higher scores. Likewise for worthwhile, the linear line follows the LOESS line consistently and so we keep the linear term in our model. Lastly, we consider a quadratic transformation for median_score.

mod_1 <- lm(suicides ~ log(unemployment_rate) + worthwhile + median_income + I(median_income^2) + living_score,  offset = os, data = suicides_complete)

Implementing the transformed explanatory terms only saw little improvement to the R-squared value to 0.340 and thus, not much change in the plot of the actual values vs fitted values. Because of this, I decided it would be best to work backwards with the current full model and use the AIC values as they are a better representation of model fit.

drop1(mod_1, test = 'F')

From the drop1 command (*), we can see that p-value for log(unemployment_rate) is greater than 0.05 and so we reject the null hypothesis of this term being insignificant in our model at the 95% confidence interval. Related to its significance is the fact that its deletion would cause the AIC of the current model to increase from 1345.5 to 1356.8. On the other hand, deletion of the quadratic median_income term variable offers the greatest minimisation in our AIC value to 1343.7. In order to further determine whether this decision is justified, we implement the stepwise AIC command.

m.backward <- stats::step(mod_1, scope = c(lower=~log(unemployment_rate)), direction = "backward")
## Start:  AIC=1345.47
## suicides ~ log(unemployment_rate) + worthwhile + median_income + 
##     I(median_income^2) + living_score
## 
##                      Df Sum of Sq   RSS    AIC
## - I(median_income^2)  1     24.67 26488 1343.7
## - median_income       1     45.45 26509 1344.0
## - worthwhile          1    146.44 26610 1345.1
## <none>                            26463 1345.5
## - living_score        1    338.42 26802 1347.2
## 
## Step:  AIC=1343.74
## suicides ~ log(unemployment_rate) + worthwhile + median_income + 
##     living_score
## 
##                 Df Sum of Sq   RSS    AIC
## - worthwhile     1    146.60 26635 1343.4
## <none>                       26488 1343.7
## - median_income  1    352.30 26840 1345.7
## - living_score   1    358.83 26847 1345.7
## 
## Step:  AIC=1343.38
## suicides ~ log(unemployment_rate) + median_income + living_score
## 
##                 Df Sum of Sq   RSS    AIC
## <none>                       26635 1343.4
## - median_income  1    286.54 26921 1344.6
## - living_score   1    465.28 27100 1346.5

From the above output, it is suggested that we remove worthwhile and the quadratic median_income terms from the full model. In particular, it is highly plausible that the relationship between the worthwhile variable and suicides can be explained by other variables in the model, hence making this removal valid. In fact, additional removal of the quadratic median_income term would possibly imply that the aforementioned relationship could be explained by the linear median_income term. Indeed, when observing the smoothing plots, one can see that worthwhile and median_income appear very similar, and so, only one term, in this case median_income, may be needed in the model. However, when we implement this into a reduced model, we can a slight decrease in our R-squared value 0.337. Conversely, removing only the quadratic median_income term sees the R-squared remain constant at 0.340. Moreover, because of this somewhat negligible difference in the AIC of the model without the worthwhile term (1343.38) and with the worthwhile term (1343.74), I decided to keep the term in the model for ease of interpretation with regards to question 1.

With regards to the residual plots (see Fig.?), we note the tendency for there to be increasing variation in the residuals as the fitted values increase. This phenomenon is known as heteroskedasticity and hence implies that we are dealing with a non-normal distribution due to a non-constant variance. This relates to the point made earlier using the histogram which revealed a strong positive skew in the data. To solve this problem, we can build our way up to implementing a non-normal distribution to ultimately model our data.

Following this discovery, I decided to create a transformed linear model by transforming the response variable and using the reduced model. Here, we implement the log offset as we are using the log of the response.

mod_2 <- lm(log(suicides) ~ log(unemployment_rate) + median_income + living_score + worthwhile,  offset = log_os, data = suicides_complete)

The transformed linear model shows great improvement as the R-squared has increased significantly to a value of 0.762 so we continue with this model. Considering the correlation plots, we can investigate whether there is any interaction taking place between the explanatory variables. In particular, out of the entire dataset, the most correlation is seen between unemployment_rate and median_income then between unemployment_rate and worthwhile. Though the correlation is only moderate, it may be an indication of some interaction and so we plot their respective interaction plots below.

ur_income <- suicides_complete %>% 
     ggplot(aes(x = unemployment_rate,
                y = suicide_rate,color = income)) +
     geom_point() + geom_smooth(formula = y ~ poly(x,1), method = lm, se=F) +
  xlab("unemployment rate (log)")  + scale_x_continuous(trans = "log")

ur_worth <- suicides_complete %>% 
     ggplot(aes(x = unemployment_rate,
                y = suicide_rate,color = wellbeing)) +
     geom_point() + geom_smooth(formula = y ~ poly(x,1), method = lm, se=F) +
  xlab("unemployment rate (log)")  + scale_x_continuous(trans = "log")

ur_income | ur_worth

Figure 6: Interaction Plots

With differing levels of income and wellbeing, we can see that the plotted lines cross at differing unemployment rates, thus implying that there is interaction taking place between the respective variables. But how significant is this interaction in terms of improving our model? Adding the interaction of log(unemployment_rate) and median_income sees a considerable improvement in our R-squared value to 0.792. On the other hand, the interaction of log(unemployment_rate) and worthwhile only sees less improvement in our R-squared value to 0.773. In order to further verify the significance of each interaction term, we conduct an ANOVA using the original transformed linear model and the models containing the added interaction terms below.

mod_3 <- lm(log(suicides) ~ log(unemployment_rate) + median_income + living_score + worthwhile + log(unemployment_rate)*median_income ,  offset = log_os, data = suicides_complete)

mod_3a <- lm(log(suicides) ~ log(unemployment_rate) + median_income + living_score + worthwhile + log(unemployment_rate)*worthwhile ,  offset = log_os, data = suicides_complete)



anova(mod_2,mod_3,test="LRT")
## Analysis of Variance Table
## 
## Model 1: log(suicides) ~ log(unemployment_rate) + median_income + living_score + 
##     worthwhile
## Model 2: log(suicides) ~ log(unemployment_rate) + median_income + living_score + 
##     worthwhile + log(unemployment_rate) * median_income
##   Res.Df    RSS Df Sum of Sq Pr(>Chi)   
## 1    292 39.305                         
## 2    291 38.319  1   0.98546 0.006226 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
anova(mod_2,mod_3a,test="LRT")
## Analysis of Variance Table
## 
## Model 1: log(suicides) ~ log(unemployment_rate) + median_income + living_score + 
##     worthwhile
## Model 2: log(suicides) ~ log(unemployment_rate) + median_income + living_score + 
##     worthwhile + log(unemployment_rate) * worthwhile
##   Res.Df    RSS Df Sum of Sq Pr(>Chi)  
## 1    292 39.305                        
## 2    291 38.691  1   0.61422  0.03161 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Both generated p-values for the models the respective interaction terms prove to be less than 0.05, meaning that we can reject the null hypothesis of these interaction terms being insignificant in our model at the 95% confidence interval. In particular, the p-value corresponding to the log(unemployment_rate) * median_income term is seen to be considerably smaller than the p-value for the log(unemployment_rate) * worthwhile term. Considering this, we can infer that the log(unemployment_rate) * median_income term has greater significance with regards to our model, and so we retain this term rather than the log(unemployment_rate) * worthwhile term. In my final search for an improved model, I decided to implement two generalised linear models below: one poisson with a log link and one gaussian with a log link.

mod_glm <- glm(suicides ~ log(unemployment_rate) + median_income + living_score + worthwhile + log(unemployment_rate)*median_income, data = suicides_complete, family = gaussian(link="log"), offset = log_os)


mod_glm2 <- glm(suicides ~ log(unemployment_rate) + median_income + living_score + worthwhile + log(unemployment_rate)*median_income, data = suicides_complete, family = poisson(link="log"), offset = log_os)

AIC(mod_glm,mod_glm2)
##          df     AIC
## mod_glm   7 1812.61
## mod_glm2  6 1769.95

Fitting with these generalised linear models shows notable improvement to our R-squared value to 0.810 under the gaussian model and 0.806 under the poisson model. In order to determine which one to include in our final model, we consider the AIC of each model which is seen to be 1812.61 under the gaussian model and 1769.95 under the poisson model. The poisson model thus minimises the AIC considerably and so our final and best fitted model can be studied by the summary output below (*). This closely follows the point we made previously regarding the heteroskedasticity and thus non-constant variance of the data. In particular, we know that for a poisson distribution variance increases as mean increases and so the use of this distribution is clearly the best choice. Finally, note how the corresponding p-values for each term, except than worthwhile, is less than 0.05, implying that those terms is significant here. Again, we reiterate the decision to retain the worthwhile term is for ease of interpretation and we will discuss possible reasons why this term ends up being insignificant.

summary(mod_glm2)
data_resid<- suicides_complete %>% gather_residuals(initial_model,mod_1,
                                        .resid = "residuals")

data_fv<- suicides_complete %>% gather_predictions(initial_model,mod_1,
                                       .pred ="fitted_vals",
                                       type = "response")

data_models <- data_fv %>% left_join(data_resid)
lm_fitted_plots<-data_models %>% 
    ggplot(aes(suicides, fitted_vals)) + 
      geom_point() + geom_smooth()+
        geom_abline(intercept = 0,
                    slope = 1,
                    col = "red") +facet_wrap(~model, nrow=2)
 

lm_resid_plots <- data_models  %>%
     ggplot(aes(fitted_vals, residuals)) + 
     geom_point() +
     geom_abline(intercept = 0, 
                 slope = 0, 
                 col = "red")  + 
     geom_smooth() +facet_wrap(~model, nrow=2)

lm_fitted_plots+lm_resid_plots
glm_trans_models <- suicides_complete %>% 
     spread_predictions(mod_2,mod_3,mod_3a,mod_glm,mod_glm2,
                        type="response") %>% 
     mutate(mod_2 = exp(mod_2),mod_3 = exp(mod_3),mod_3a = exp(mod_3a)) %>% 
     pivot_longer(c("mod_2","mod_3","mod_3a","mod_glm","mod_glm2"),
                  names_to = "model",
                  values_to = "fitted_vals") %>% 
     mutate(residuals = suicides - fitted_vals)

glm_trans_fv<- glm_trans_models %>%
    ggplot(aes(suicides, fitted_vals)) + 
      geom_point() + 
        geom_abline(intercept = 0,
                    slope = 1,
                    col = "red")+
  geom_smooth() +facet_wrap(~model, nrow=2)
         

fit_vs_res_glm<-glm_trans_models %>%
     ggplot(aes(fitted_vals, residuals)) + 
     geom_point() +
     geom_abline(intercept = 0, 
                 slope = 0, 
                 col = "red")  + 
  geom_smooth() +
      facet_wrap(~model, nrow=2)

glm_trans_fv+fit_vs_res_glm

Figure 7: Actual vs Fitted (left) and Fitted vs Residuals (Right) for Transformed and GLM Models

data_fv %>% 
  group_by(model) %>% 
    summarise(R2 = cor(suicides,fitted_vals)^2) %>% 
      kable(digits=3) %>% 
        kable_styling(full_width = FALSE)

glm_trans_models %>% 
  group_by(model) %>% 
    summarise(R2 = cor(suicides,fitted_vals)^2) %>% 
      kable(digits=3) %>% 
        kable_styling(full_width = FALSE) 

With regards to the residual plots, note how the model building process up to the final poisson model slowly reduces the effect of heteroskedasticity. For easier visualisation we can refer to the Pearsons residuals corresponding to our final model as seen below and observe that the residuals are now evenly distributed about the zero reference line (*). When the fitted values exceed 75 there is overestimation of suicides, this of which is negligible as there is only one point above that range.

persons_final <- residualPlot(mod_glm2, variable = "fitted", type = "pearson",
              plot = TRUE, quadratic = FALSE, smooth=TRUE, main = "Pearson Residual Plot for Final Model")
final_pred <- suicides_complete %>% 
  spread_predictions(mod_glm2,
                     type="response") %>% 
  pivot_longer(c("mod_glm2"),
               names_to = "model",
               values_to = "fitted_vals") %>% 
  mutate(residuals = suicides - fitted_vals)


living_fit <- suicides_complete%>%
  ggplot(aes(x = living_score, y = suicides)) +
  geom_point() +
  geom_smooth(data = final_pred, aes(y=round(fitted_vals,0)), method = "glm", method.args = list(family = poisson(link="log")), se = TRUE)+ ylab("suicides per 100K")

ur_fit <- suicides_complete%>%
  ggplot(aes(x = unemployment_rate, y = suicides)) +
  geom_point() +
  geom_smooth(data = final_pred, aes(y=round(fitted_vals,0)), method = "glm", method.args = list(family = poisson(link="log")), se = TRUE)+ ylab("suicides per 100K")

mi_fit <- suicides_complete%>%
  ggplot(aes(x = median_income, y = suicides)) +
  geom_point() +
  geom_smooth(data = final_pred, aes(y=round(fitted_vals,0)), method = "glm", method.args = list(family = poisson(link="log")), se = TRUE)+ ylab("suicides per 100K")

ww_fit <- suicides_complete%>%
  ggplot(aes(x = worthwhile, y = suicides)) +
  geom_point() +
  geom_smooth(data = final_pred, aes(y=round(fitted_vals,0)), method = "glm", method.args = list(family = poisson(link="log")), se = TRUE) + ylab("suicides per 100K")



(living_fit | ur_fit)/(mi_fit | ww_fit)

From figure 1 from section A we know that suicides increase with increasing levels of unemployment and deprivation and decrease with increasing income and wellbeing. Intuitively this makes sense, however, when looking at the effect plots below we see a different outcome than expected.

#pred_interaction<- ggpredict(mod_glm2, c("unemployment_rate", "median_income"))
pred_ur <- plot(Effect("unemployment_rate",mod_glm2),ylab = "suicides per 100K")
pred_living <- plot(Effect("living_score",mod_glm2),ylab = "suicides per 100K")
pred_income <- plot(Effect("median_income",mod_glm2),ylab = "suicides per 100K")
pred_worth <- plot(Effect("worthwhile",mod_glm2),ylab = "suicides per 100K")

grid.arrange(pred_living, pred_worth, pred_ur, pred_income, ncol=2, nrow = 2)

#plot(pred_interaction)

#unemployment rate doesnt make sense...possible confounding due to correlated variable most likely median income so use worth model with interaction instead

# living score also does not make sense....also affected by income so confounding

Figure 8: Effect Plots We see that suicide rates tend to decrease with increasing unemployment rates and deprivation while they increase with increasing wellbeing. This is completely opposite to what we saw in the fitted curves and goes against our intuition but we know that the effect plots allow for investigation of individual variable (marginal) effects while holding other explanatory variables constant. Therefore, the reason for this difference is most likely due to the presence of a confounding variable. As we previously mentioned, median_income and unemployment_rate are moderately correlated, possibly to the point where this increase in unemployment_rate seen in figure 1 is actually due to the presence of the variable in our model. In particular, we know that as the unemployment rate declines, persons feel less suicidal (positive relationship), however we also know that as a person’s salary/income decreases, unemployment rate will increase and then they become more susceptible to suicidal thoughts. Closely related to this is the fact that less deprivation should result in less suicides, but less income as a result of less employment means an increase in deprivation, resulting in more suicidal thoughts. Likewise, increased personal wellbeing should result in less suicides, but more less as a result of less employment income means a decrease in wellbeing, resulting in more suicidal thoughts.We remove terms associated with this confounding variable and fit a revised final model as follows:

mod_final <- glm(suicides ~ log(unemployment_rate) + worthwhile + living_score, data = suicides_complete, family = poisson(link="log"), offset = log_os)

pred_ur2 <- plot(Effect("unemployment_rate",mod_final ),ylab = "suicides per 100K")
pred_living2 <- plot(Effect("living_score",mod_final ),ylab = "suicides per 100K")
pred_worth2 <- plot(Effect("worthwhile",mod_final ),ylab = "suicides per 100K")


#grid.arrange(pred_living2, pred_worth2, pred_ur2, ncol=2, nrow = 2)
tidy(mod_final) %>% 
  kable(digits = 5, 
        caption = "Final Revised Model: Estimated Parameters with Log Link Poisson GLM")  %>%  
          kable_classic(full_width = F)
Final Revised Model: Estimated Parameters with Log Link Poisson GLM
term estimate std.error statistic p.value
(Intercept) 0.25881 0.79235 0.32663 0.74394
log(unemployment_rate) 0.09958 0.05677 1.75403 0.07943
worthwhile 0.23426 0.09499 2.46621 0.01365
living_score -0.00216 0.00168 -1.28241 0.19970

The interpretation for the table above is as follows: for each extra unit that unemployment rate increases by, we expect to see a relative increase of about 10.5% (exp(0.09958)-1 \(\approx\) 0.1047068) in the average number of suicides per 100K people. Likewise, the average number of suicides double for every log(2)/(0.09958) \(\approx\) 6.96 unit increase in unemployment rate. From this we are told to expect a relative increase of about 26% in the average number of suicides per 100K people with every increase in worthwhile effects and a relative decrease of about 0.22% in the average number of suicides per 100K people with every increase in living_score; we know these inferences are misleading so we disregard them.

This improves on the unemployment_rate effect but the living_score and worthwhile effects remain the same, possibly indicating that an underlying factor is responsible for such disparity. In particular, we know that living deprivation, personal wellbeing and unemployment usually go hand in hand, as well as the fact that deprivation is strongly influenced by environmental factors. Another way to think about it is that unemployed persons may not be able to afford to live in ‘better’ environments due to lack of income, this of which affects their wellbeing. With this in mind, we investigate the effects of regional differences in the following section in hopes of improving our model.

Q2. What are the regional differences in the number of suicides in England?

reg_int0 <- suicides_complete %>% 
     ggplot(aes(x = unemployment_rate,
                y = suicide_rate,color = region)) +
     geom_point() + geom_smooth(formula = y ~ poly(x,1), method = lm, se=F) + scale_x_continuous(trans="log")
reg_int1 <- suicides_complete %>% 
     ggplot(aes(x = living_score,
                y = suicide_rate,color = region)) +
     geom_point() + geom_smooth(formula = y ~ poly(x,1), method = lm, se=F)
grid.arrange(reg_int0,reg_int1,ncol=1)

#interaction taking place

From the above plot (), we can see that interaction is taking place between the different regions and so we implement this in our revised model below. Conducting an ANOVA confirms that the log(unemployment_rate) region and living_score * region terms are significant (*).

mod_reg_0 <- glm(suicides ~ log(unemployment_rate) + living_score + worthwhile , data = suicides_complete, family = poisson(link="log"), offset = log_os)

mod_reg_final <- glm(suicides ~ log(unemployment_rate)*region + worthwhile + region*living_score, data = suicides_complete, family = poisson(link="log"), offset = log_os)


anova(mod_reg_0 ,mod_reg_final,test="LRT") # p value less than 0.05 > interaction significant
pred_ur3 <- plot(Effect("unemployment_rate",mod_reg_final ))
pred_living3 <- plot(Effect("living_score",mod_reg_final ))
pred_worth3 <- plot(Effect("worthwhile",mod_reg_final ))
pred_ggur<- ggpredict(mod_reg_final, c("unemployment_rate"))
pred_ggls<- ggpredict(mod_reg_final, c("living_score"))
pred_ggww<- ggpredict(mod_reg_final, c("worthwhile"))

par(mfrow = c(1, 2))
#plot(pred_ggur)
plot(pred_ggls) 

plot(pred_ggww)

We now see a more sensible result for the marginal effect of living_score appears to be positive in relation to suicide counts. Conversely, we still see no improvement to the worthwhile plot. This may be due to the fact that the range provided for the sampled worthwhile values proves to be very small and thus is not able to confer any significant effects in this case.

From the plot below we can see that a difference between the effect of different regions on suicide rate actually depends on the underlying assumed unemployment rates and living scores. However, note that this difference is not so significant as the intervals for each region overlap with each other.

reg_plot_0 <- plot(Effect("region",
                 mod_reg_final))

reg_plot_1 <- plot(Effect("region",
                 mod_reg_final ,
                 fixed.predictors = list(given.values = c(`log(unemployment_rate)`=log(2)))), main = "unemployment_rate of 2",ylab = "suicides per 100K")
reg_plot_2 <-  plot(Effect("region",
                 mod_reg_final ,
                 fixed.predictors = list(given.values = c(`log(unemployment_rate)`=log(7)))), main = "unemployment_rate of 7",ylab = "suicides per 100K")

reg_plot_3 <- plot(Effect("region",
                 mod_reg_final ,
                 fixed.predictors = list(given.values = c(`living_score`=10))), main = "living_score of 10",ylab = "suicides per 100K")
reg_plot_4 <-  plot(Effect("region",
                 mod_reg_final ,
                 fixed.predictors = list(given.values = c(`living_score`=40))), main = "living_score of 40",ylab = "suicides per 100K")




reg_plot_0 

#reg_plot_1 
#reg_plot_2
#reg_plot_3 
#reg_plot_4


#worthwhile and living_score insignificant...living_score influenced by income and income influenced by unemployment rate
# to see effect of regions we have to vary the unemployment variable
# unemployment seems to have more influence on suicides compared to living score (pink intervals)
#no significant regional difference as intervals interlap
tidy(mod_reg_final) %>% 
  kable(digits = 5, 
        caption = "Region Model: Estimated Parameters with Log Link Poisson GLM")  %>%  
          kable_classic(full_width = F)

Q3. Are there any difference in suicides with regards to the North-South divide?

In order to implement this analysis we must first create a new column in our existing/initial dataframe. To further catergorise the regions into North and South, I referred to this (https://geographical.co.uk/images/2020/North_South_divide/Map.png) map. For this question I opted to remove the worthwhile term from the model due to reasons discussed in the previous question.

set.seed(357)
suicides_complete$N_or_S <- rep(NA, nrow(suicides_complete))
suicides_complete[suicides_complete$region == "North East", ][, "N_or_S"] <- "North"
suicides_complete[suicides_complete$region == "North West", ][, "N_or_S"] <- "North"
suicides_complete[suicides_complete$region == "Yorkshire and The Humber", ][, "N_or_S"] <- "North"
suicides_complete[suicides_complete$region == "East Midlands", ][, "N_or_S"] <- "North"
suicides_complete[suicides_complete$region == "West Midlands", ][, "N_or_S"] <- "North"
suicides_complete[suicides_complete$region == "East of England", ][, "N_or_S"] <- "South"
suicides_complete[suicides_complete$region == "London", ][, "N_or_S"] <- "South"
suicides_complete[suicides_complete$region == "South West", ][, "N_or_S"] <- "South"
suicides_complete[suicides_complete$region == "South East", ][, "N_or_S"] <- "South"

mod_N_S <- glm(suicides ~ N_or_S*log(unemployment_rate) + N_or_S*living_score , data = suicides_complete, family = poisson(link="log"), offset = log_os)
N_S_plot_0 <- plot(Effect("N_or_S",
                 mod_N_S))


N_S_plot_1 <- plot(Effect("N_or_S",
                 mod_N_S ,
                 fixed.predictors = list(given.values = c(`log(unemployment_rate)`=log(2)))), main = "unemployment_rate of 2",ylab = "suicides per 100K")
N_S_plot_2 <-  plot(Effect("N_or_S",
                 mod_N_S ,
                 fixed.predictors = list(given.values = c(`log(unemployment_rate)`=log(7)))), main = "unemployment_rate of 7",ylab = "suicides per 100K")

N_S_plot_3 <- plot(Effect("N_or_S",
                 mod_N_S ,
                 fixed.predictors = list(given.values = c(`living_score`=10))), main = "living_score of 10",ylab = "suicides per 100K")
N_S_plot_4 <-  plot(Effect("N_or_S",
                 mod_N_S ,
                 fixed.predictors = list(given.values = c(`living_score`=40))), main = "living_score of 40",ylab = "suicides per 100K")



N_S_plot_0

#N_S_plot_1 
#N_S_plot_2 
#N_S_plot_3
#N_S_plot_4 

#grid.arrange(N_S_plot_1,N_S_plot_2,N_S_plot_3,N_S_plot_4,  ncol=2, nrow = 2)
region_models <- suicides_complete %>% 
     spread_predictions(mod_reg_0,mod_reg_final,mod_N_S,
                        type="response") %>% 
     pivot_longer(c("mod_reg_0","mod_reg_final","mod_N_S"),
                  names_to = "model",
                  values_to = "fitted_vals") %>% 
     mutate(residuals = suicides - fitted_vals)

region_fv<- region_models %>%
    ggplot(aes(suicides, fitted_vals)) + 
      geom_point() + geom_smooth() +
        geom_abline(intercept = 0,
                    slope = 1,
                    col = "red")  +
           facet_wrap(~model)

fit_vs_res_region<-region_models %>%
     ggplot(aes(fitted_vals, residuals)) + 
     geom_point() +
     geom_abline(intercept = 0, 
                 slope = 0, 
                 col = "red")  + 
     geom_smooth() +
     facet_wrap(~ model, nrow = 2) + 
     ggtitle("Fitted response values vs Residuals")

region_models %>% 
  group_by(model) %>% 
    summarise(R2 = cor(suicides,fitted_vals)^2) %>% 
      kable(digits=3) %>% 
        kable_styling(full_width = FALSE)

persons_final_reg <- residualPlot(mod_reg_final, variable = "fitted", type = "pearson",
              plot = TRUE, quadratic = FALSE, smooth=TRUE, main = "Pearson Residual Plot for Final Region Model")

region_fv
fit_vs_res_region


AIC(mod_reg_0,mod_reg_final,mod_N_S)

References

Include your references in this section. The references below are examples of books and a website.

  1. Wickham, H. ggplot2: Elegant Graphics for Data Analysis on-line version

  2. Wickham, H. & Grolemund, G. R for Data Science. on-line version

  3. Department of Maths website

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgU3VpY2lkZSBSYXRlcyBpbiBFbmdsYW5kIgphdXRob3I6ICJab2UgR2FuZXNzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICBrZWVwX3RleDogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwphbHdheXNfYWxsb3dfaHRtbDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSx3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgpgYGB7ciBsaWJyYXJpZXMsZWNobz0gRkFMU0V9CiMgaW5jbHVkZSB5b3VyIGxpYnJhcmllcyBoZXJlCiMgdXNlIGVjaG8gPSBGQUxTRSBpZiB5b3UgZG8gbm90IHdhbnQgdGhlIENvZGUgYnV0dG9uIHRvIGFwcGVhciAKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobW9kZWxyKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2xpcHB5KQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGVmZmVjdHMpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KG1nY3YpCmxpYnJhcnkobW9tZW50cykKbGlicmFyeShyY29tcGFuaW9uKQpsaWJyYXJ5KHJzdGF0aXgpCmxpYnJhcnkoZ2dlZmZlY3RzKQpsaWJyYXJ5KGNhcikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ3JpZEdyYXBoaWNzKQpsaWJyYXJ5KGdncHVicikKbGlicmFyeShnZ3Bsb3QyKQoKYGBgCgoKPCEtLQpZb3UgY2FuIGluY2x1ZGUgbm9uLWNvZGluZyBjb21tZW50cyB1c2luZyB0aGVzZSBkZWxpbWl0ZXJzLiBXaGF0IGlzIHdyaXR0ZW4gaW5zaWRlIHRoZXNlIGRlbGltaXRlcnMgd29udCBiZSBrbml0dGVkIGludG8gdGhlIGh0bWwgZG9jdW1lbnQhCgpEbyBub3QgY2hhbmdlIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRvY3VtZW50LCBqdXN0IGZpbGwgaW4gdGhlIHNlY3Rpb25zIGFzIGluZGljYXRlZCAKWW91IGNhbiBvbmx5IGNoYW5nZSB0aGUgaGVhZGluZ3MgaW5kaWNhdGVkIHdpdGggWypdCi0tPgoKCmBgYHtyIGRhdGFfcmVhZGluZyxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CgpzdWljaWRlc19kYXRhIDwtIHJlYWRfY3N2KCJodHRwczovL3Blb3BsZS5iYXRoLmFjLnVrL2thaTIxL01BNTAyNTgvZGF0YS9DVzFfZGF0YS5jc3YiKSAKCmBgYAoKYGBge3IgZWZmZWN0c30KCiNnbGltcHNlKHN1aWNpZGVzX2RhdGEpCgojc3VtbWFyeShzdWljaWRlc19kYXRhKQoKIyBpdCBjYW4gYmUgc2VlbiB0aGF0IDUgY29sdW1ucyBoYXZlIG11bHRpcGxlIG1pc3NpbmcgdmFsdWVzCiMgd2Ugb21pdCB0aGVzZSBieSBydW5uaW5nIHRoZSBjb2RlIGJlbG93CgpzdWljaWRlc19jb21wbGV0ZSA8LSBzdWljaWRlc19kYXRhW2NvbXBsZXRlLmNhc2VzKHN1aWNpZGVzX2RhdGEpLF0KYGBgCgojIEEuIFF1ZXN0aW9ucwojIyBJbnRyb2R1Y3Rpb24KCkZvciB0aGlzIGFuYWx5c2lzLCBkYXRhIGZyb20gMzI2IGxvY2FsIGF1dGhvcml0aWVzIGluIEVuZ2xhbmQgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBzdWljaWRlcywgcGVyc29uYWwgd2VsbC1iZWluZywgdW5lbXBsb3ltZW50LCBpbmNvbWUsIGRlcHJpdmF0aW9uIGFuZCBwb3B1bGF0aW9uIHdhcyBjb25zaWRlcmVkLiBUaGlzIHJlcG9ydCBhaW1zIHRvIGRldGVybWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgZXhwbGFuYXRvcnkgZmFjdG9ycyBhbmQgc3VpY2lkZXMuIFRoZSBpbXBvcnRhbmNlIG9mIHRoaXMgcmVwb3J0IGlzIHRoZXJlZm9yZSByZWZsZWN0ZWQgaW4gdGhlIGZhY3QgdGhhdCBzdHVkeWluZyB0aGVzZSByZWxhdGlvbnNoaXBzIHdpbGwgbGVhZCB0byBhIGJldHRlciB1bmRlcnN0YW5kaW5nIG9mIHdoYXQgZXhhY3RseSBpbmZsdWVuY2VzIGFuIGluZGl2aWR1YWwgdG8gdW5kZXJnbyBzdWljaWRhbCB0aG91Z2h0cy4gV2l0aCBiZXR0ZXIga25vd2xlZGdlIG9mIHRoaXMsIHdlIGNhbiBhZGRyZXNzIHRob3NlIGluZmx1ZW50aWFsIGZhY3RvcnMgaW4gYW4gYXR0ZW1wdCB0byBtaXRpZ2F0ZSB0aGUgb2NjdXJyZW5jZSBvZiBzdWljaWRhbCBpbmNpZGVuY2VzIGluIHRoZSBnZW5lcmFsIHBvcHVsYXRpb24uCgpOQjogd2hlcmUgKCopIGFwcGVhcnMsIHRoYXQgcGxvdC90YWJsZS9ncmFwaCBldGMuIHdhcyBub3QgaW5jbHVkZWQgZHVlIHRvIHRoZSBwYWdlIGxpbWl0IGJ1dCBpcyBub3QgY2VudHJhbCB0byB0aGUgbWFpbiBhbmFseXNpcy4uLnJlZmVyIHRvIHJtYXJrZG93biBmaWxlIGZvciBvcmlnaW5hbCBvdXRwdXQKCgojIyAgUTEuIFRvIHdoYXQgZXh0ZW50IGFyZSBwZXJzb25hbCB3ZWxsLWJlaW5nLCB1bmVtcGxveW1lbnQsIGluY29tZSBhbmQgZGVwcml2YXRpb24gIGFzc29jaWF0ZWQgd2l0aCB0aGUgbnVtYmVyIG9mIHN1aWNpZGVzIGluIEVuZ2xhbmQ/CgohW0ZpdHRlZCBDdXJ2ZXMgZm9yIFJlc3BlY3RpdmUgRXhwbGFuYXRvcnkgVmFyaWFibGVzIEFnYWluc3QgU3VpY2lkZSBSYXRlXSgvVXNlcnMvem9lL0Rvd25sb2Fkcy91bmkgb2YgYmF0aCBtc2MvczIvYXBwbGllZCBzdGF0cy9maWcxLnBuZykKClRoZSBvdmVyYWxsIHRyZW5kIG9mIGVhY2ggZmFjdG9yIGlzIHNob3duIGluIGZpZ3VyZSAxLiBJdCBjYW4gYmUgb2JzZXJ2ZWQgdGhhdCBsaXZpbmcgc2NvcmUgKGRlcHJpdmF0aW9uKSBhbmQgdW5lbXBsb3ltZW50IHJhdGUgaGF2ZSBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCB3aXRoIHN1aWNpZGUgcmF0ZSB3aGVyZWFzIG1lZGlhbiBpbmNvbWUgYW5kIHdvcnRod2hpbGUgKHdlbGxiZWluZykgaGF2ZSBhIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCB3aXRoIHNhbWUuIE1vcmUgc3BlY2lmaWNpYWxseSwgaW5jcmVhc2VzIGluIGRlcHJpdmF0aW9uIGFuZCB1bmVtcGxveW1lbnQgYW5kIGRlY3JlYXNlcyBpbiBpbmNvbWUgYW5kIHBlcnNvbmFsIHdlbGxiZWluZyByZXN1bHQgaW4gbW9yZSBwZXJzb25zIGNvbW1pdHRpbmcgc3VpY2lkZS4gV2UgYWxzbyByZWNvZ25pc2UgdGhlIHJlbGF0aW9uc2hpcHMgZWFjaCBvZiB0aGVzZSBmYWN0b3JzIGhhdmUgd2l0aCBlYWNoIG90aGVyIGFuZCBob3cgdGhleSBhZmZlY3Qgc3VpY2lkZSByYXRlcyBqb2ludGx5LiBGb3IgZXhhbXBsZSwgZGVwcml2YXRpb24gaW50dWl0aXZlbHkgc2hvdWxkIGJlIHJlbGF0ZWQgdG8gaGlnaCB1bmVtcGxveW1lbnQgcmF0ZXMgYW5kIHNwZWNpZmljYWxseSBsb3cgaW5jb21lIGFuZCB0aGUgY29tYmluYXRpb24gb2YgdGhlc2UgZmFjdG9ycywgaW4gdHVybiB3b3VsZCBoYXZlIGEgbmVnYXRpdmUgZWZmZWN0IG9uIG9uZXMgd2VsbGJlaW5nLCB1bHRpbWF0ZWx5IGxlYXZpbmcgcm9vbSBmb3Igc3VpY2lkYWwgdGhvdWdodHMuCgoKCiMjICBRMi4gV2hhdCBhcmUgdGhlIHJlZ2lvbmFsIGRpZmZlcmVuY2VzIGluIHRoZSBudW1iZXIgb2Ygc3VpY2lkZXMgaW4gRW5nbGFuZD8KCmBgYHtyIHJlZ30KCnJlZ2lvbl9kYXRhIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICBncm91cF9ieShyZWdpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3N1aWNpZGVzID0gbWVhbihzdWljaWRlcyksCiAgICAgICAgICAgICNtYXhfc3VpY2lkZXMgPSBtYXgoc3VpY2lkZXMpLAogICAgICAgICAgICAjbWluX3N1aWNpZGVzID0gbWluKHN1aWNpZGVzKSwKICAgICAgICAgICAgYXZlcmFnZV9zdWljaWRlX3JhdGUgPSAoKHN1bShzdWljaWRlcykvc3VtKHBvcHVsYXRpb24pKSoxZTUpLAogICAgICAgICAgICB0b3RhbF9zdWljaWRlcyA9IHN1bShzdWljaWRlcyksCiAgICAgICAgICAgIHRvdGFsX3BvcCA9IHN1bShwb3B1bGF0aW9uKSkKcmVnaW9uX2RhdGEgJT4lICBrYWJsZShkaWdpdHMgPSAyLAogICAgICAgIGNhcHRpb24gPSAiUmVnaW9uYWwgU3VpY2lkZXMgU3VtbWFyeSBTdGF0aXN0aWNzIiwKICAgICAgICBhbGlnbj0iYyIpICU+JSAgCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpCgpgYGAKTG9va2luZyBhdCB0aGUgdGFibGUgYWJvdmUsIHdlIGNhbiBpbmZlciB0aGF0IFlvcmtzaGlyZSBhbmQgVGhlIEh1bWJlciwgTm9ydGggRWFzdCBhbmQgRWFzdCBvZiBFbmdsYW5kIGhhdmUgdGhlIHRocmVlIGhpZ2hlc3Qgc3VpY2lkZSByYXRlcyB3aGVyZWFzIExvbmRvbiwgU291dGggRWFzdCBhbmQgRWFzdCBNaWRsYW5kcyBoYXZlIHRoZSB0aHJlZSBsb3dlc3QuIFRoZSBhdmVyYWdlIHN1aWNpZGUgcmF0ZSBhbW9uZyB0aG9zZSBsaXZpbmcgaW4gdGhlIHJlZ2lvbiBvZiBZb3Jrc2hpcmUgYW5kIFRoZSBIdW1iZXIgd2FzIGFwcHJveGltYXRlbHkgMS41IG1vcmUgdGhhbiB0aG9zZSBsaXZpbmcgaW4gTG9uZG9uLiBJbnRlcmVzdGluZ2x5LCB0aGUgdGhyZWUgcmVnaW9ucyB3aXRoIHRoZSBoaWdoZXN0IHN1aWNpZGUgcmF0ZXMgYXJlIHNpdHVhdGVkIGluIHRoZSBOb3J0aCBvZiB0aGUgVUsgd2hlcmVhcyB0aGUgdHdvIGxvd2VzdCBzdWljaWRlIHJhdGVzIG9yaWdpbmF0ZSBmcm9tIHRoZSBTb3V0aC4gV2Ugbm90ZSB0aGF0IHRoZSBkaWZmZXJlbmNlIGlzIG5vdCBwYXJ0aWN1bGFybHkgc2lnbmlmaWNhbnQgKGFzIHRoZSBwaW5rIGludGVydmFscyBpbiB0aGUgZ3JhcGhzIGJlbG93IGludGVybGFwKSBidXQgaW4gb3JkZXIgdG8gcXVhbnRpZnkgdGhlIGZ1cnRoZXIgcXVhbnRpZnkgdGhlIGVmZmVjdHMgd2UgYXJlIGludmVzdGlnYXRpbmcsIHdlIHRha2UgdGhlIGluc3RhbmNlIG9mIGhpZ2ggYW5kIGxvdyB1bmVtcGxveW1lbnQgcmF0ZXMgYXMgYSByZWZlcmVuY2UuIElmIGFsbCByZWdpb25zIHdlcmUgdG8gaGF2ZSB0aGUgc2FtZSB1bmVtcGxveW1lbnQgcmF0ZSwgdGhlIGF2ZXJhZ2Ugc3VpY2lkZSByYXRlIHdvdWxkIGJlIGZhaXJseSBzaW1pbGFyIGFjcm9zcyBlYWNoIHJlZ2lvbiwgYXMgc2VlbiBpbiB0aGUgdGFibGUgKHJlZmVyIHRvIGZpZ3VyZSAzKS4gSG93ZXZlciwgdW5kZXIgYSBsb3cgdW5lbXBsb3ltZW50IHJhdGUgb2YgMi4wLCB3ZSBvYnNlcnZlIHN1YnRsZSBjaGFuZ2VzIGluIHRoZSBzdWljaWRlIHJhdGVzIChtb3N0IGluY3JlYXNlcyksIGJ1dCB0aGUgcmVsYXRpdmUgc2hhcGUgb2YgdGhlIGdyYXBoIGlzIHVuY2hhbmdlZC4gQSBoaWdoZXIgdW5lbXBsb3ltZW50IHJhdGUgb2YgNy4wIHNlZXMgc3Vic3RhbnRpYWwgY2hhbmdlcyB3aXRoIGJvdGggdGhlIGF2ZXJhZ2Ugc3VpY2lkZSByYXRlIGFuZCByZWxhdGl2ZSBzaGFwZSBvZiB0aGUgZ3JhcGguIE9uZSBpbnRlcmVzdGluZyB0aGluZyB0byBub3RlIGlzIHRoYXQgdGhlIHJlZ2lvbnMgd2hvIGluaXRpYWxseSBoYWQgdGhlIGhpZ2hlc3Qgc3VpY2lkZSByYXRlcyBhcmUgbm93IGFtb25nIHRoZSBsb3dlc3QsIGluZmVycmluZyB0aGF0IG90aGVyIGZhY3RvcnMgc3VjaCBhcyBkZXByaXZhdGlvbiwgZXNwZWNpYWxseSBpbiB0aGUgY2FzZSBvZiByZWdpb25hbCBjb25jZXJucywgYWxzbyBhZmZlY3QgdGhlIGF2ZXJhZ2Ugc3VpY2lkZXMgcmF0ZXMuCgoKIVtFZmZlY3Qgb2YgTG93IFVuZW1wbG95bWVudCBSYXRlcyBvbiBSZWdpb25hbCBTdWljaWRlIFJhdGVzXSgvVXNlcnMvem9lL0Rvd25sb2Fkcy91bmkgb2YgYmF0aCBtc2MvczIvYXBwbGllZCBzdGF0cy9maWc1LnBuZykgCgohW0VmZmVjdCBvZiBIaWdoIFVuZW1wbG95bWVudCBSYXRlcyBvbiBSZWdpb25hbCBTdWljaWRlIFJhdGVzXSgvVXNlcnMvem9lL0Rvd25sb2Fkcy91bmkgb2YgYmF0aCBtc2MvczIvYXBwbGllZCBzdGF0cy9maWc0LnBuZykKCiMjICBRMy4gQXJlIHRoZXJlIGFueSBkaWZmZXJlbmNlIGluIHN1aWNpZGVzIHdpdGggcmVnYXJkcyB0byB0aGUgTm9ydGgtU291dGggZGl2aWRlPwoKCk1hcmdpbmFsaXNpbmcgdGhlIHJlZ2lvbnMgZXZlbiBmdXJ0aGVyIGludG8gTm9ydGggYW5kIFNvdXRoIHByb3ZlcyB0aGF0IHRoZXJlIGlzIGEgc29tZXdoYXQgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBvdmVyYWxsLiBBdCBsb3cgdW5lbXBsb3ltZW50IHJhdGVzIGFuZCBsaXZpbmcgc2NvcmVzIHRoZSBub3J0aCB0ZW5kcyB0byBoYXZlIG1vcmUgc3VpY2lkZXMgYnV0IHRoZSBkaWZmZXJlbmNlIGlzIGRlYmF0YWJsZSBhcyB0aGUgaW50ZXJ2YWxzIGp1c3QgYmFyZWx5IG92ZXJsYXAuIEF0IGhpZ2hlciB1bmVtcGxveW1lbnQgcmF0ZXMgYm90aCByZWdpb25zIHNlZSBzaW1pbGFyIHN1aWNpZGUgcmF0ZXMgKGFwcHJveCAwLjUgZGlmZmVyZW5jZSBiZXR3ZWVuIHN1aWNpZGUgcmF0ZSksIGltcGx5aW5nIHRoYXQgdGhpcyBoYXMgc2lnbmlmaWNhbnQgaW5mbHVlbmNlIG92ZXIgc3VpY2lkZSByYXRlcyBpbiBib3RoIHJlZ2lvbnMuIExpa2V3aXNlLCBhdCBoaWdoZXIgbGV2ZWxzIG9mIGRlcHJpdmF0aW9uLCB0aGVyZSBpcyBhcHByb3hpbWF0ZWx5IDEuMCBkaWZmZXJlbmNlIGluIHRoZSBzdWljaWRlIHJhdGVzIGJldHdlZW4gYm90aCByZWdpb25zLiBUaHVzLCBvdmVyYWxsIHRoZXJlIGlzIGEgZGlmZmVyZW5jZSBpbiBzdWljaWRlcyB3aXRoIHJlZ2FyZHMgdG8gdGhlIE5vcnRoLVNvdXRoIGRpdmlkZSwgbW9zdGx5IG93aW5nIHRvIGRpZmZlcmVuY2VzIGluIHVuZW1wbG95bWVudCByYXRlcyBhbmQgZGVwcml2YXRpb247IGluIG90aGVyIHdvcmRzLCB0aGUgTm9ydGggc2VlcyBoaWdoZXIgdW5lbXBsb3ltZW50IHJhdGVzIGFuZCBtb3JlIGRlcHJpdmF0aW9uIHdoZW4gY29tcGFyZWQgdG8gdGhlIFNvdXRoLiBXaGVuIHdlIGNvbnNpZGVyIHRoZSB0cmFkaXRpb25hbCBub3Rpb25zIHN1cnJvdW5kaW5nIHRoZSBOb3J0aC1Tb3V0aCBkaXZpZGUgaW4gRW5nbGFuZCwgdGhpcyBjb25jbHVzaW9uIHN1cHBvcnRzIGFzcGVjdHMgcmVnYXJkaW5nIHRoZSBzb2Npb2Vjb25vbWljIG1ha2V1cCBvZiB0aGVzZSByZWdpb25zLiAKCiFbRWZmZWN0IG9mIFVuZW1wbG95bWVudCBhbmQgRGVwcml2YXRpb24gb24gUmVnaW9uYWwgU3VpY2lkZSBSYXRlc10oL1VzZXJzL3pvZS9Eb3dubG9hZHMvdW5pIG9mIGJhdGggbXNjL3MyL2FwcGxpZWQgc3RhdHMvZmlnOC5wbmcpCgoKIyBCLiBNYXRlcmlhbHMgYW5kIE1ldGhvZHMKCiMjIERhdGEKCmBgYHtyIHN1bW1hcnksIHJlc3VsdHM9J2hpZGUnfQoKc3RkX2RldiA8LSBhcHBseShzdWljaWRlc19jb21wbGV0ZVssLWMoMSwzKV0sIDIsIHNkKSAgIyBvbWl0dGluZyBmaXJzdCBhbmQgdGhpcmQgY29sdW1ucyBmcm9tIHN1bW1hcnkgYXMgdGhleSBhcmUgY2hhcmFjdGVycwptaW5fdmFsIDwtIGFwcGx5KHN1aWNpZGVzX2NvbXBsZXRlWywtYygxLDMpXSwgMiwgbWluKQptYXhfdmFsIDwtIGFwcGx5KHN1aWNpZGVzX2NvbXBsZXRlWywtYygxLDMpXSwgMiwgbWF4KQptZWFuX3ZhbCA8LSBhcHBseShzdWljaWRlc19jb21wbGV0ZVssLWMoMSwzKV0sIDIsIG1lYW4pCnRvdGFsX3ZhbCA8LSBhcHBseShzdWljaWRlc19jb21wbGV0ZVssLWMoMSwzKV0sIDIsIHN1bSkKCgpkYXRhLmZyYW1lKG1pbj1taW5fdmFsLCBtYXg9bWF4X3ZhbCwgbWVhbj1tZWFuX3ZhbCxzZD1zdGRfZGV2LCB0b3RhbCA9IHRvdGFsX3ZhbCkgJT4lIAogIGthYmxlKGRpZ2l0cyA9IDIsCiAgICAgICAgY2FwdGlvbiA9ICJTdWljaWRlcyBTdW1tYXJ5IFN0YXRpc3RpY3MiLAogICAgICAgIGFsaWduPSJjIikgJT4lICAKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikKCiMgNDc0OCBzdWljaWRlcyByZWNvcmRlZCBpbiAyMDE4CmBgYAoKQWZ0ZXIgY3JlYXRpbmcgYSBkYXRhZnJhbWUgd2l0aG91dCBtaXNzaW5nIHZhbHVlcywgd2UgZmlyc3QgaW52ZXN0aWdhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHBvcHVsYXRpb24gc2l6ZSBhbmQgdGhlIG51bWJlciBvZiBzdWljaWRlcy4gSW50dWl0aXZlbHksIGl0IGlzIHVzdWFsbHkgYXNzdW1lZCB0aGF0IHRoZSBudW1iZXIgb2Ygc3VpY2lkZXMgaW5jcmVhc2VzIHdpdGggZ3Jvd2luZyBwb3B1bGF0aW9uIHNpemUgYW5kIHRoaXMgaXMgaW5kZWVkIG9ic2VydmVkIGluIHRoaXMgY2FzZSwgYXMgdGhlcmUgaXMgYSBzdHJvbmcgbGluZWFyIHJlbGF0aW9uc2hpcCBzZWVuIGluIHRoZSBwbG90IGJlbG93ICgqKS4gSG93ZXZlciwgdGhpcyBjcmVhdGVzIGFuIGlzc3VlIGluIHRlcm1zIG9mIG91ciBhbmFseXNpcywgYXMgd2UgYXJlIHJlcXVpcmVkIHRvIGRldGVybWluZSB0aGUgYXNzb2NpYXRpb24gb2YgdGhlIG90aGVyIGZvdXIgZmFjdG9ycyB3aXRoIHN1aWNpZGVzLiBNb3JlIHNwZWNpZmljYWxseSwgc2luY2UgYSBncmVhdCBhbW91bnQgb2YgdGhlIHN1aWNpZGVzIGNhbiBiZSBleHBsYWluZWQgYnkgdGhlIHBvcHVsYXRpb24gc2l6ZSwgd2Ugc2VlIHRoZSBuZWVkIHRvIGhvbGQgcG9wdWxhdGlvbiBjb25zdGFudCAoYXNzdW1lIGl0IHRvIGJlIGEgdmFsdWUgb2YgMSkgc28gdGhhdCBpdCBpcyBub3QgZXN0aW1hdGVkIGJ5IG91ciBtb2RlbC4gV2UgaW1wbGVtZW50IHRoaXMgYnkgY3JlYXRpbmcgdHdvIG9mZnNldHM6IG9uZSBpbiB0ZXJtcyBvZiBsb2cocG9wdWxhdGlvbi8xMDAsMDAwKSBhbmQganVzdCBwb3B1bGF0aW9uLzEwMCwwMDA7IHRoZXNlIHdpbGwgYmUgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIGhhdmluZyB0byB0cnkgZGlmZmVyZW50IG1vZGVscyBmdXJ0aGVyIG9uLgoKYGBge3IgcG9wLGV2YWw9RkFMU0V9CnBvcF9wbG90IDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICBncm91cF9ieShyZWdpb24pICU+JQogIGdncGxvdChhZXMoeCA9IHBvcHVsYXRpb24seSA9IHN1aWNpZGVzKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChmb3JtdWxhID0geX54LG1ldGhvZCA9IGxtKSAKcGxvdChwb3BfcGxvdCkKCiNyZWdpb25fcGxvdCA8LSBwb3BfcGxvdCArIGZhY2V0X3dyYXAofnJlZ2lvbikKCmBgYAoKSW4gb3JkZXIgdG8gdmlzdWFsaXNlIHRoZSBkYXRhLCB3ZSBmaXJzdCBwbG90IGEgaGlzdG9ncmFtIG9mIHRoZSBmcmVxdWVuY3kgb2YgdGhlIG51bWJlciBvZiBzdWljaWRlcywgd2hpY2ggZGVtb25zdHJhdGVzIGEgc3Ryb25nIHBvc2l0aXZlIHNrZXcgYXMgc2VlbiBiZWxvdyAoKikuIEhlbmNlLCB3ZSBzaG91bGQgYW50aWNpcGF0ZSBoYXZpbmcgdG8gZWl0aGVyIGZpdCBhIHBvaXNzb24gZ2VuZXJhbGlzZWQgbGluZWFyIG1vZGVsIG9yIGEgdHJhbnNmb3JtZWQgbGluZWFyIG1vZGVsIGluIG9yZGVyIHRvIGJlc3QgbW9kZWwgdGhlIGRhdGEuCgpgYGB7ciBoaXN0LGV2YWw9RkFMU0V9CnBsb3ROb3JtYWxIaXN0b2dyYW0oc3VpY2lkZXNfY29tcGxldGUkc3VpY2lkZXMpCmBgYAoKSW4gb3JkZXIgdG8gaW1wbGVtZW50IGZ1cnRoZXIgYW5hbHlzaXMsIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcmUgZ2VuZXJhdGVkIGluIHRlcm1zIG9mIGxvdywgbWVkaXVtIGFuZCBoaWdoLCB3aXRoIHJlZ2FyZHMgdG8gaW5jb21lLCB3ZWxsYmVpbmcsIHVuZW1wbG95bWVudCBhbmQgZGVwcml2YXRpb24uIFdlIGVtcGxveSB2aXN1YWxpc2F0aW9uIG9mIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIHRoZSBudW1lcmljYWwgdmFyaWFibGVzICgqKS4gV2Ugbm90ZSB0aGUgaGlnaCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHBvcHVsYXRpb24gYW5kIHN1aWNpZGVzIGFzIHdlIGFsc28gZXhwbGFpbmVkIGVhcmxpZXIuIE5vbmUgb2Ygb3VyIG90aGVyIHZhcmlhYmxlcyBzZWVtIHRvIGhhdmUgYSBwYXJ0aWN1bGFybHkgaGlnaCBjb3JyZWxhdGlvbiB3aXRoIHN1aWNpZGVzLCBob3dldmVyLCBzb21lIHZhcmlhYmxlcywgc3VjaCBhcyBpbmNvbWUgYW5kIHVuZW1wbG95bWVudCwgc2VlbSB0byBkaXNwbGF5IG1vZGVyYXRlIGNvcnJlbGF0aW9uIGJldHdlZW4gZWFjaCBvdGhlci4gV2Ugbm90ZSB0aGlzIGFzIHRoZXkgbWF5IGJlIGFuIGluZGljYXRpb24gb2YgaW50ZXJhY3Rpb24gdGFraW5nIHBsYWNlLgoKYGBge3IgbXV0YXRlfQpzdWljaWRlc19jb21wbGV0ZSA8LSBzdWljaWRlc19jb21wbGV0ZSAlPiUgCiAgICAgbXV0YXRlKGluY29tZSA9IGN1dF9udW1iZXIobWVkaWFuX2luY29tZSwzKSkgJT4lIAogICAgIG11dGF0ZShpbmNvbWUgPSBmY3RfcmVjb2RlKGluY29tZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubG93ID0gbGV2ZWxzKGluY29tZSlbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tZWRpdW0gPSBsZXZlbHMoaW5jb21lKVsyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmhpZ2ggPSBsZXZlbHMoaW5jb21lKVszXSkpCgpzdWljaWRlc19jb21wbGV0ZSA8LSBzdWljaWRlc19jb21wbGV0ZSAlPiUgCiAgICAgbXV0YXRlKGRlcHJpdmF0aW9uID0gY3V0X251bWJlcihsaXZpbmdfc2NvcmUsMykpICU+JSAKICAgICBtdXRhdGUoZGVwcml2YXRpb24gPSBmY3RfcmVjb2RlKGRlcHJpdmF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5sb3cgPSBsZXZlbHMoZGVwcml2YXRpb24pWzFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWVkaXVtID0gbGV2ZWxzKGRlcHJpdmF0aW9uKVsyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmhpZ2ggPSBsZXZlbHMoZGVwcml2YXRpb24pWzNdKSkKCnN1aWNpZGVzX2NvbXBsZXRlIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICAgICBtdXRhdGUod2VsbGJlaW5nID0gY3V0X251bWJlcih3b3J0aHdoaWxlLDMpKSAlPiUgCiAgICAgbXV0YXRlKHdlbGxiZWluZyA9IGZjdF9yZWNvZGUod2VsbGJlaW5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5sb3cgPSBsZXZlbHMod2VsbGJlaW5nKVsxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm1lZGl1bSA9IGxldmVscyh3ZWxsYmVpbmcpWzJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuaGlnaCA9IGxldmVscyh3ZWxsYmVpbmcpWzNdKSkKCnN1aWNpZGVzX2NvbXBsZXRlIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICAgICBtdXRhdGUodW5lbXBsb3ltZW50ID0gY3V0X251bWJlcih1bmVtcGxveW1lbnRfcmF0ZSwzKSkgJT4lIAogICAgIG11dGF0ZSh1bmVtcGxveW1lbnQgPSBmY3RfcmVjb2RlKHVuZW1wbG95bWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubG93ID0gbGV2ZWxzKHVuZW1wbG95bWVudClbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tZWRpdW0gPSBsZXZlbHModW5lbXBsb3ltZW50KVsyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmhpZ2ggPSBsZXZlbHModW5lbXBsb3ltZW50KVszXSkpCgpzdWljaWRlc19jb21wbGV0ZSA8LSBzdWljaWRlc19jb21wbGV0ZSAlPiUgbXV0YXRlKHN1aWNpZGVfcmF0ZSA9IHN1aWNpZGVzL3BvcHVsYXRpb24qMWU1LCBvcyA9IChwb3B1bGF0aW9uLzFlNSksIGxvZ19vcyA9IGxvZyhwb3B1bGF0aW9uLzFlNSkpCmBgYAoKYGBge3IgbmV3LCBmaWcuc2hvdz0naGlkZScsIHJlc3VsdHM9J2hpZGUnfQprYWJsZShjb3Ioc3VpY2lkZXNfY29tcGxldGVbLC1jKDEsMyw5LDEwLDExLDEyKV0pLAogICAgICBkaWdpdHM9MikgJT4lICAKICAgICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRiApCnBhaXJzKHN1aWNpZGVzX2NvbXBsZXRlWywtYygxLDMsOSwxMCwxMSwxMiwxMywxNCwxNSldKQoKCmBgYAoKIyMgICBRMS4gVG8gd2hhdCBleHRlbnQgYXJlIHBlcnNvbmFsIHdlbGwtYmVpbmcsIHVuZW1wbG95bWVudCwgaW5jb21lIGFuZCBkZXByaXZhdGlvbiAgYXNzb2NpYXRlZCB3aXRoIHRoZSBudW1iZXIgb2Ygc3VpY2lkZXMgaW4gRW5nbGFuZD8KCk15IGZpcnN0IHRob3VnaHQgd2FzIHRvIGNvbnN0cnVjdCBhIHNpbXBsZSBsaW5lYXIgbW9kZWwgdXNpbmcgdGhlIHJlcXVpcmVkIHZhcmlhYmxlcyB0byBiZSBlc3RpbWF0ZWQgYW5kIHRoZSBub24tbG9nIG9mZnNldCAoYXMgdGhpcyBpcyBhIG5vbi10cmFuc2Zvcm1lZCBtb2RlbCkuIFRoaXMgbW9kZWwgcmVzdWx0ZWQgaW4gYW4gUi1zcXVhcmVkIHZhbHVlIG9mIDAuMzM0LCBob3dldmVyIHRoZSBwbG90IG9mIHRoZSBhY3R1YWwgdmFsdWVzIHZzIGZpdHRlZCB2YWx1ZXMgcHJvdmVkIHRvIGJlIHZlcnkgcG9vci4gSW4gb3JkZXIgdG8gaW1wcm92ZSBvbiB0aGlzLCBJIGRlY2lkZWQgaXQgbWlnaHQgYmUgYmVzdCB0byBwbG90IGVhY2ggZXhwbGFuYXRvcnkgdmFyaWFibGUgYWdhaW5zdCBzdWljaWRlcyBhbmQgdXNlIExPRVNTIHNtb290aGluZyB0byBiZXR0ZXIgdmlzdWFsaXNlIHRoZWlyIHJlbGF0aW9uc2hpcC4gCgpgYGB7ciBtb2QwfQppbml0aWFsX21vZGVsIDwtIGxtKHN1aWNpZGVzIH4gdW5lbXBsb3ltZW50X3JhdGUgKyB3b3J0aHdoaWxlICsgbWVkaWFuX2luY29tZSArIGxpdmluZ19zY29yZSwgIG9mZnNldCA9IG9zLCBkYXRhID0gc3VpY2lkZXNfY29tcGxldGUpCmBgYAoKYGBge3IgbG9lc3MsZXZhbD1UUlVFfQoKbHNfcGxvdDwtc3VpY2lkZXNfY29tcGxldGUgJT4lCiAgZ2dwbG90KGFlcyhsaXZpbmdfc2NvcmUsIHN1aWNpZGVzKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0sIGZvcm11bGEgPSB5IH4gcG9seSh4LCBkZWdyZWUgPSAxLCByYXcgPSBUKSwKICAgICAgICAgICAgICBzZSA9IEYsIGFlcyhjb2wgPSAiYmx1ZSIpKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBULCBhZXMoY29sID0gInJlZCIpLCBsaW5ldHlwZSA9ImRhc2hlZCIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgZm9ybXVsYSA9IHkgfiBwb2x5KHgsIGRlZ3JlZSA9IDIsIHJhdyA9IFQpLAogICAgICAgICAgICAgIHNlID0gRiwgYWVzKGNvbCA9ICJncmVlbiIpKSArCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkobmFtZSA9ICJTbW9vdGggVHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTGluZWFyIiwgIkxPRVNTIiwiUXVhZHJhdGljIiksIGd1aWRlID0gImxlZ2VuZCIpCgp1cl9wbG90PC1zdWljaWRlc19jb21wbGV0ZSAlPiUKICBnZ3Bsb3QoYWVzKHVuZW1wbG95bWVudF9yYXRlLCBzdWljaWRlcykpICsKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBmb3JtdWxhID0geSB+IHBvbHkoeCwxKSwKICAgICAgICAgICAgICBzZSA9IEYsIGFlcyhjb2wgPSAiYmx1ZSIpKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBULCBhZXMoY29sID0gInJlZCIpLCBsaW5ldHlwZSA9ImRhc2hlZCIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgZm9ybXVsYSA9IHkgfiBwb2x5KHgsIGRlZ3JlZSA9IDIsIHJhdyA9IFQpLAogICAgICAgICAgICAgIHNlID0gRiwgYWVzKGNvbCA9ICJncmVlbiIpKSsgeGxhYigidW5lbXBsb3ltZW50X3JhdGUobG9nKSIpICsKICBzY2FsZV9jb2xvcl9pZGVudGl0eShuYW1lID0gIlNtb290aCBUeXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygiYmx1ZSIsICJyZWQiLCAiZ3JlZW4iKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJMaW5lYXIiLCAiTE9FU1MiLCJRdWFkcmF0aWMiKSwgZ3VpZGUgPSAibGVnZW5kIikKCm1pX3Bsb3Q8LXN1aWNpZGVzX2NvbXBsZXRlICU+JQogIGdncGxvdChhZXMobWVkaWFuX2luY29tZSwgc3VpY2lkZXMpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0sIGZvcm11bGEgPSB5IH4gcG9seSh4LCBkZWdyZWUgPSAxLCByYXcgPSBUKSwKICAgICAgICAgICAgICBzZSA9IEYsIGFlcyhjb2wgPSAiYmx1ZSIpKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBULCBhZXMoY29sID0gInJlZCIpLCBsaW5ldHlwZSA9ImRhc2hlZCIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSBsbSwgZm9ybXVsYSA9IHkgfiBwb2x5KHgsIGRlZ3JlZSA9IDIsIHJhdyA9IFQpLAogICAgICAgICAgICAgIHNlID0gRiwgYWVzKGNvbCA9ICJncmVlbiIpKSArCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkobmFtZSA9ICJTbW9vdGggVHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTGluZWFyIiwgIkxPRVNTIiwiUXVhZHJhdGljIiksIGd1aWRlID0gImxlZ2VuZCIpCgp3d19wbG90PC1zdWljaWRlc19jb21wbGV0ZSAlPiUKICBnZ3Bsb3QoYWVzKHdvcnRod2hpbGUsIHN1aWNpZGVzKSkgKwogIGdlb21fcG9pbnQoKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtLCBmb3JtdWxhID0geSB+IHBvbHkoeCwgZGVncmVlID0gMSwgcmF3ID0gVCksCiAgICAgICAgICAgICAgc2UgPSBGLCBhZXMoY29sID0gImJsdWUiKSkgKwogIGdlb21fc21vb3RoKHNlID0gVCwgYWVzKGNvbCA9ICJyZWQiKSwgbGluZXR5cGUgPSJkYXNoZWQiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0sIGZvcm11bGEgPSB5IH4gcG9seSh4LCBkZWdyZWUgPSAyLCByYXcgPSBUKSwKICAgICAgICAgICAgICBzZSA9IEYsIGFlcyhjb2wgPSAiZ3JlZW4iKSkrCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkobmFtZSA9ICJTbW9vdGggVHlwZSIsIAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTGluZWFyIiwgIkxPRVNTIiwiUXVhZHJhdGljIiksIGd1aWRlID0gImxlZ2VuZCIpCgoKCihsc19wbG90IHwgdXJfcGxvdCkvKHd3X3Bsb3QgfCBtaV9wbG90KQpgYGAKRmlndXJlIDU6IFNtb290aGluZwoKQWxvbmcgd2l0aCBMT0VTUyBzbW9vdGhpbmcsIEkgYWxzbyBpbmNsdWRlZCBsaW5lYXIgYW5kIHF1YWRyYXRpYyBzbW9vdGhpbmcgZm9yIGVhc2Ugb2YgYW5hbHlzaXMuIEZpcnN0bHksIGl0IHNob3VsZCBiZSBub3RlZCB0aGF0IHVuZW1wbG95bWVudF9yYXRlIHdhcyBsb2ctdHJhbnNmb3JtZWQgYXMgaXQgYWxsb3dlZCBmb3IgYmV0dGVyIGxpbmVhciBzbW9vdGhpbmc7IHdoaWxlIHRoZSBsaW5lYXIgbGluZSBzbGlnaHRseSBvdmVyZXN0aW1hdGVzIGZvciBoaWdoZXIgdW5lbXBsb3ltZW50IHJhdGVzLCBpdCBzdGlsbCBmb2xsb3dzIHRoZSBnZW5lcmFsIGxpbmVhciB0cmVuZCB3ZWxsIGFuZCBzbyB3ZSB3aWxsIGNvbnNpZGVyIHRoaXMgdHJhbnNmb3JtZWQgdmFyaWFibGUgaW4gb3VyIG1vZGVsLiBMaXZpbmdfc2NvcmUgY2FuIGJlIHNlZW4gdG8gYXBwZWFyIGZhaXJseSBjdWJpYyBidXQgdGhpcyBtYXkganVzdCBiZSBwb3NzaWJsZSBkdWUgdG8gZXh0cmVtZSB2YWx1ZXMgKG9yIG91dGxpZXJzKS4gSW5zdGVhZCwgd2UgY29uc2lkZXIgdGhlIGxpbmVhciB0cmVuZCB3aGljaCBmb2xsb3dzIHRoZSBMT0VTUyBsaW5lIGZhaXJseSBjb25zaXN0ZW50bHksIG9ubHkgc2xpZ2h0bHkgdW5kZXJlc3RpbWF0aW5nIGF0IGxvd2VyIGxpdmluZyBzY29yZXMgYW5kIG92ZXJlc3RpbWF0aW5nIGV2ZW4gbGVzcyBhdCBoaWdoZXIgc2NvcmVzLiBMaWtld2lzZSBmb3Igd29ydGh3aGlsZSwgdGhlIGxpbmVhciBsaW5lIGZvbGxvd3MgdGhlIExPRVNTIGxpbmUgY29uc2lzdGVudGx5IGFuZCBzbyB3ZSBrZWVwIHRoZSBsaW5lYXIgdGVybSBpbiBvdXIgbW9kZWwuIExhc3RseSwgd2UgY29uc2lkZXIgYSBxdWFkcmF0aWMgdHJhbnNmb3JtYXRpb24gZm9yIG1lZGlhbl9zY29yZS4KCmBgYHtyIG1vZF8xfQoKbW9kXzEgPC0gbG0oc3VpY2lkZXMgfiBsb2codW5lbXBsb3ltZW50X3JhdGUpICsgd29ydGh3aGlsZSArIG1lZGlhbl9pbmNvbWUgKyBJKG1lZGlhbl9pbmNvbWVeMikgKyBsaXZpbmdfc2NvcmUsICBvZmZzZXQgPSBvcywgZGF0YSA9IHN1aWNpZGVzX2NvbXBsZXRlKQoKYGBgCkltcGxlbWVudGluZyB0aGUgdHJhbnNmb3JtZWQgZXhwbGFuYXRvcnkgdGVybXMgb25seSBzYXcgbGl0dGxlIGltcHJvdmVtZW50IHRvIHRoZSBSLXNxdWFyZWQgdmFsdWUgdG8gMC4zNDAgYW5kIHRodXMsIG5vdCBtdWNoIGNoYW5nZSBpbiB0aGUgcGxvdCBvZiB0aGUgYWN0dWFsIHZhbHVlcyB2cyBmaXR0ZWQgdmFsdWVzLiBCZWNhdXNlIG9mIHRoaXMsIEkgZGVjaWRlZCBpdCB3b3VsZCBiZSBiZXN0IHRvIHdvcmsgYmFja3dhcmRzIHdpdGggdGhlIGN1cnJlbnQgZnVsbCBtb2RlbCBhbmQgdXNlIHRoZSBBSUMgdmFsdWVzIGFzIHRoZXkgYXJlIGEgYmV0dGVyIHJlcHJlc2VudGF0aW9uIG9mIG1vZGVsIGZpdC4KCmBgYHtyIGRyb3AxLCByZXN1bHRzPSdoaWRlJ30KCmRyb3AxKG1vZF8xLCB0ZXN0ID0gJ0YnKQoKYGBgCkZyb20gdGhlIGRyb3AxIGNvbW1hbmQgKCopLCB3ZSBjYW4gc2VlIHRoYXQgcC12YWx1ZSBmb3IgbG9nKHVuZW1wbG95bWVudF9yYXRlKSBpcyBncmVhdGVyIHRoYW4gMC4wNSBhbmQgc28gd2UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgb2YgdGhpcyB0ZXJtIGJlaW5nIGluc2lnbmlmaWNhbnQgaW4gb3VyIG1vZGVsIGF0IHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbC4gUmVsYXRlZCB0byBpdHMgc2lnbmlmaWNhbmNlIGlzIHRoZSBmYWN0IHRoYXQgaXRzIGRlbGV0aW9uIHdvdWxkIGNhdXNlIHRoZSBBSUMgb2YgdGhlIGN1cnJlbnQgbW9kZWwgdG8gaW5jcmVhc2UgZnJvbSAxMzQ1LjUgdG8gMTM1Ni44LiBPbiB0aGUgb3RoZXIgaGFuZCwgZGVsZXRpb24gb2YgdGhlIHF1YWRyYXRpYyBtZWRpYW5faW5jb21lIHRlcm0gdmFyaWFibGUgb2ZmZXJzIHRoZSBncmVhdGVzdCBtaW5pbWlzYXRpb24gaW4gb3VyIEFJQyB2YWx1ZSB0byAxMzQzLjcuIEluIG9yZGVyIHRvIGZ1cnRoZXIgZGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkZWNpc2lvbiBpcyBqdXN0aWZpZWQsIHdlIGltcGxlbWVudCB0aGUgc3RlcHdpc2UgQUlDIGNvbW1hbmQuIAoKYGBge3IgQUlDfQoKbS5iYWNrd2FyZCA8LSBzdGF0czo6c3RlcChtb2RfMSwgc2NvcGUgPSBjKGxvd2VyPX5sb2codW5lbXBsb3ltZW50X3JhdGUpKSwgZGlyZWN0aW9uID0gImJhY2t3YXJkIikKCmBgYAoKRnJvbSB0aGUgYWJvdmUgb3V0cHV0LCBpdCBpcyBzdWdnZXN0ZWQgdGhhdCB3ZSByZW1vdmUgd29ydGh3aGlsZSBhbmQgdGhlIHF1YWRyYXRpYyBtZWRpYW5faW5jb21lIHRlcm1zIGZyb20gdGhlIGZ1bGwgbW9kZWwuIEluIHBhcnRpY3VsYXIsIGl0IGlzIGhpZ2hseSBwbGF1c2libGUgdGhhdCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHdvcnRod2hpbGUgdmFyaWFibGUgYW5kIHN1aWNpZGVzIGNhbiBiZSBleHBsYWluZWQgYnkgb3RoZXIgdmFyaWFibGVzIGluIHRoZSBtb2RlbCwgaGVuY2UgbWFraW5nIHRoaXMgcmVtb3ZhbCB2YWxpZC4gSW4gZmFjdCwgYWRkaXRpb25hbCByZW1vdmFsIG9mIHRoZSBxdWFkcmF0aWMgbWVkaWFuX2luY29tZSB0ZXJtIHdvdWxkIHBvc3NpYmx5IGltcGx5IHRoYXQgdGhlIGFmb3JlbWVudGlvbmVkIHJlbGF0aW9uc2hpcCBjb3VsZCBiZSBleHBsYWluZWQgYnkgdGhlIGxpbmVhciBtZWRpYW5faW5jb21lIHRlcm0uIEluZGVlZCwgd2hlbiBvYnNlcnZpbmcgdGhlIHNtb290aGluZyBwbG90cywgb25lIGNhbiBzZWUgdGhhdCB3b3J0aHdoaWxlIGFuZCBtZWRpYW5faW5jb21lIGFwcGVhciB2ZXJ5IHNpbWlsYXIsIGFuZCBzbywgb25seSBvbmUgdGVybSwgaW4gdGhpcyBjYXNlIG1lZGlhbl9pbmNvbWUsIG1heSBiZSBuZWVkZWQgaW4gdGhlIG1vZGVsLiBIb3dldmVyLCB3aGVuIHdlIGltcGxlbWVudCB0aGlzIGludG8gYSByZWR1Y2VkIG1vZGVsLCB3ZSBjYW4gYSBzbGlnaHQgZGVjcmVhc2UgaW4gb3VyIFItc3F1YXJlZCB2YWx1ZSAwLjMzNy4gQ29udmVyc2VseSwgcmVtb3Zpbmcgb25seSB0aGUgcXVhZHJhdGljIG1lZGlhbl9pbmNvbWUgdGVybSBzZWVzIHRoZSBSLXNxdWFyZWQgcmVtYWluIGNvbnN0YW50IGF0IDAuMzQwLiBNb3Jlb3ZlciwgYmVjYXVzZSBvZiB0aGlzIHNvbWV3aGF0IG5lZ2xpZ2libGUgZGlmZmVyZW5jZSBpbiB0aGUgQUlDIG9mIHRoZSBtb2RlbCB3aXRob3V0IHRoZSB3b3J0aHdoaWxlIHRlcm0gKDEzNDMuMzgpIGFuZCB3aXRoIHRoZSB3b3J0aHdoaWxlIHRlcm0gKDEzNDMuNzQpLCBJIGRlY2lkZWQgdG8ga2VlcCB0aGUgdGVybSBpbiB0aGUgbW9kZWwgZm9yIGVhc2Ugb2YgaW50ZXJwcmV0YXRpb24gd2l0aCByZWdhcmRzIHRvIHF1ZXN0aW9uIDEuCgoKV2l0aCByZWdhcmRzIHRvIHRoZSByZXNpZHVhbCBwbG90cyAoc2VlIEZpZy4/KSwgd2Ugbm90ZSB0aGUgdGVuZGVuY3kgZm9yIHRoZXJlIHRvIGJlIGluY3JlYXNpbmcgdmFyaWF0aW9uIGluIHRoZSByZXNpZHVhbHMgYXMgdGhlIGZpdHRlZCB2YWx1ZXMgaW5jcmVhc2UuIFRoaXMgcGhlbm9tZW5vbiBpcyBrbm93biBhcyBoZXRlcm9za2VkYXN0aWNpdHkgYW5kIGhlbmNlIGltcGxpZXMgdGhhdCB3ZSBhcmUgZGVhbGluZyB3aXRoIGEgbm9uLW5vcm1hbCBkaXN0cmlidXRpb24gZHVlIHRvIGEgbm9uLWNvbnN0YW50IHZhcmlhbmNlLiBUaGlzIHJlbGF0ZXMgdG8gdGhlIHBvaW50IG1hZGUgZWFybGllciB1c2luZyB0aGUgaGlzdG9ncmFtIHdoaWNoIHJldmVhbGVkIGEgc3Ryb25nIHBvc2l0aXZlIHNrZXcgaW4gdGhlIGRhdGEuIFRvIHNvbHZlIHRoaXMgcHJvYmxlbSwgd2UgY2FuIGJ1aWxkIG91ciB3YXkgdXAgdG8gaW1wbGVtZW50aW5nIGEgbm9uLW5vcm1hbCBkaXN0cmlidXRpb24gdG8gdWx0aW1hdGVseSBtb2RlbCBvdXIgZGF0YS4KCkZvbGxvd2luZyB0aGlzIGRpc2NvdmVyeSwgSSBkZWNpZGVkIHRvIGNyZWF0ZSBhIHRyYW5zZm9ybWVkIGxpbmVhciBtb2RlbCBieSB0cmFuc2Zvcm1pbmcgdGhlIHJlc3BvbnNlIHZhcmlhYmxlIGFuZCB1c2luZyB0aGUgcmVkdWNlZCBtb2RlbC4gSGVyZSwgd2UgaW1wbGVtZW50IHRoZSBsb2cgb2Zmc2V0IGFzIHdlIGFyZSB1c2luZyB0aGUgbG9nIG9mIHRoZSByZXNwb25zZS4KYGBge3IgbW9kMn0KCm1vZF8yIDwtIGxtKGxvZyhzdWljaWRlcykgfiBsb2codW5lbXBsb3ltZW50X3JhdGUpICsgbWVkaWFuX2luY29tZSArIGxpdmluZ19zY29yZSArIHdvcnRod2hpbGUsICBvZmZzZXQgPSBsb2dfb3MsIGRhdGEgPSBzdWljaWRlc19jb21wbGV0ZSkKCmBgYAoKVGhlIHRyYW5zZm9ybWVkIGxpbmVhciBtb2RlbCBzaG93cyBncmVhdCBpbXByb3ZlbWVudCBhcyB0aGUgUi1zcXVhcmVkIGhhcyBpbmNyZWFzZWQgc2lnbmlmaWNhbnRseSB0byBhIHZhbHVlIG9mIDAuNzYyIHNvIHdlIGNvbnRpbnVlIHdpdGggdGhpcyBtb2RlbC4gQ29uc2lkZXJpbmcgdGhlIGNvcnJlbGF0aW9uIHBsb3RzLCB3ZSBjYW4gaW52ZXN0aWdhdGUgd2hldGhlciB0aGVyZSBpcyBhbnkgaW50ZXJhY3Rpb24gdGFraW5nIHBsYWNlIGJldHdlZW4gdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4gSW4gcGFydGljdWxhciwgb3V0IG9mIHRoZSBlbnRpcmUgZGF0YXNldCwgdGhlIG1vc3QgY29ycmVsYXRpb24gaXMgc2VlbiBiZXR3ZWVuIHVuZW1wbG95bWVudF9yYXRlIGFuZCBtZWRpYW5faW5jb21lIHRoZW4gYmV0d2VlbiB1bmVtcGxveW1lbnRfcmF0ZSBhbmQgd29ydGh3aGlsZS4gVGhvdWdoIHRoZSBjb3JyZWxhdGlvbiBpcyBvbmx5IG1vZGVyYXRlLCBpdCBtYXkgYmUgYW4gaW5kaWNhdGlvbiBvZiBzb21lIGludGVyYWN0aW9uIGFuZCBzbyB3ZSBwbG90IHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJhY3Rpb24gcGxvdHMgYmVsb3cuCgpgYGB7ciBpbnRlcmFjdGlvbn0KCgp1cl9pbmNvbWUgPC0gc3VpY2lkZXNfY29tcGxldGUgJT4lIAogICAgIGdncGxvdChhZXMoeCA9IHVuZW1wbG95bWVudF9yYXRlLAogICAgICAgICAgICAgICAgeSA9IHN1aWNpZGVfcmF0ZSxjb2xvciA9IGluY29tZSkpICsKICAgICBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChmb3JtdWxhID0geSB+IHBvbHkoeCwxKSwgbWV0aG9kID0gbG0sIHNlPUYpICsKICB4bGFiKCJ1bmVtcGxveW1lbnQgcmF0ZSAobG9nKSIpICArIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2ciKQoKdXJfd29ydGggPC0gc3VpY2lkZXNfY29tcGxldGUgJT4lIAogICAgIGdncGxvdChhZXMoeCA9IHVuZW1wbG95bWVudF9yYXRlLAogICAgICAgICAgICAgICAgeSA9IHN1aWNpZGVfcmF0ZSxjb2xvciA9IHdlbGxiZWluZykpICsKICAgICBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChmb3JtdWxhID0geSB+IHBvbHkoeCwxKSwgbWV0aG9kID0gbG0sIHNlPUYpICsKICB4bGFiKCJ1bmVtcGxveW1lbnQgcmF0ZSAobG9nKSIpICArIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2ciKQoKdXJfaW5jb21lIHwgdXJfd29ydGgKCmBgYApGaWd1cmUgNjogSW50ZXJhY3Rpb24gUGxvdHMKCldpdGggZGlmZmVyaW5nIGxldmVscyBvZiBpbmNvbWUgYW5kIHdlbGxiZWluZywgd2UgY2FuIHNlZSB0aGF0IHRoZSBwbG90dGVkIGxpbmVzIGNyb3NzIGF0IGRpZmZlcmluZyB1bmVtcGxveW1lbnQgcmF0ZXMsIHRodXMgaW1wbHlpbmcgdGhhdCB0aGVyZSBpcyBpbnRlcmFjdGlvbiB0YWtpbmcgcGxhY2UgYmV0d2VlbiB0aGUgcmVzcGVjdGl2ZSB2YXJpYWJsZXMuIEJ1dCBob3cgc2lnbmlmaWNhbnQgaXMgdGhpcyBpbnRlcmFjdGlvbiBpbiB0ZXJtcyBvZiBpbXByb3Zpbmcgb3VyIG1vZGVsPyBBZGRpbmcgdGhlIGludGVyYWN0aW9uIG9mIGxvZyh1bmVtcGxveW1lbnRfcmF0ZSkgYW5kIG1lZGlhbl9pbmNvbWUgc2VlcyBhIGNvbnNpZGVyYWJsZSBpbXByb3ZlbWVudCBpbiBvdXIgUi1zcXVhcmVkIHZhbHVlIHRvIDAuNzkyLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIGludGVyYWN0aW9uIG9mIGxvZyh1bmVtcGxveW1lbnRfcmF0ZSkgYW5kIHdvcnRod2hpbGUgb25seSBzZWVzIGxlc3MgaW1wcm92ZW1lbnQgaW4gb3VyIFItc3F1YXJlZCB2YWx1ZSB0byAwLjc3My4gSW4gb3JkZXIgdG8gZnVydGhlciB2ZXJpZnkgdGhlIHNpZ25pZmljYW5jZSBvZiBlYWNoIGludGVyYWN0aW9uIHRlcm0sIHdlIGNvbmR1Y3QgYW4gQU5PVkEgdXNpbmcgdGhlIG9yaWdpbmFsIHRyYW5zZm9ybWVkIGxpbmVhciBtb2RlbCBhbmQgdGhlIG1vZGVscyBjb250YWluaW5nIHRoZSBhZGRlZCBpbnRlcmFjdGlvbiB0ZXJtcyBiZWxvdy4KCmBgYHtyIG1vZDN9Cgptb2RfMyA8LSBsbShsb2coc3VpY2lkZXMpIH4gbG9nKHVuZW1wbG95bWVudF9yYXRlKSArIG1lZGlhbl9pbmNvbWUgKyBsaXZpbmdfc2NvcmUgKyB3b3J0aHdoaWxlICsgbG9nKHVuZW1wbG95bWVudF9yYXRlKSptZWRpYW5faW5jb21lICwgIG9mZnNldCA9IGxvZ19vcywgZGF0YSA9IHN1aWNpZGVzX2NvbXBsZXRlKQoKbW9kXzNhIDwtIGxtKGxvZyhzdWljaWRlcykgfiBsb2codW5lbXBsb3ltZW50X3JhdGUpICsgbWVkaWFuX2luY29tZSArIGxpdmluZ19zY29yZSArIHdvcnRod2hpbGUgKyBsb2codW5lbXBsb3ltZW50X3JhdGUpKndvcnRod2hpbGUgLCAgb2Zmc2V0ID0gbG9nX29zLCBkYXRhID0gc3VpY2lkZXNfY29tcGxldGUpCgoKCmFub3ZhKG1vZF8yLG1vZF8zLHRlc3Q9IkxSVCIpCmFub3ZhKG1vZF8yLG1vZF8zYSx0ZXN0PSJMUlQiKQoKYGBgCkJvdGggZ2VuZXJhdGVkIHAtdmFsdWVzIGZvciB0aGUgbW9kZWxzIHRoZSByZXNwZWN0aXZlIGludGVyYWN0aW9uIHRlcm1zIHByb3ZlIHRvIGJlIGxlc3MgdGhhbiAwLjA1LCBtZWFuaW5nIHRoYXQgd2UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIHRoZXNlIGludGVyYWN0aW9uIHRlcm1zIGJlaW5nIGluc2lnbmlmaWNhbnQgaW4gb3VyIG1vZGVsIGF0IHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbC4gSW4gcGFydGljdWxhciwgdGhlIHAtdmFsdWUgY29ycmVzcG9uZGluZyB0byB0aGUgbG9nKHVuZW1wbG95bWVudF9yYXRlKSAqIG1lZGlhbl9pbmNvbWUgdGVybSBpcyBzZWVuIHRvIGJlIGNvbnNpZGVyYWJseSBzbWFsbGVyIHRoYW4gdGhlIHAtdmFsdWUgZm9yIHRoZSBsb2codW5lbXBsb3ltZW50X3JhdGUpICogd29ydGh3aGlsZSB0ZXJtLiBDb25zaWRlcmluZyB0aGlzLCB3ZSBjYW4gaW5mZXIgdGhhdCB0aGUgbG9nKHVuZW1wbG95bWVudF9yYXRlKSAqIG1lZGlhbl9pbmNvbWUgdGVybSBoYXMgZ3JlYXRlciBzaWduaWZpY2FuY2Ugd2l0aCByZWdhcmRzIHRvIG91ciBtb2RlbCwgYW5kIHNvIHdlIHJldGFpbiB0aGlzIHRlcm0gcmF0aGVyIHRoYW4gdGhlIGxvZyh1bmVtcGxveW1lbnRfcmF0ZSkgKiB3b3J0aHdoaWxlIHRlcm0uIEluIG15IGZpbmFsIHNlYXJjaCBmb3IgYW4gaW1wcm92ZWQgbW9kZWwsIEkgZGVjaWRlZCB0byBpbXBsZW1lbnQgdHdvIGdlbmVyYWxpc2VkIGxpbmVhciBtb2RlbHMgYmVsb3c6IG9uZSBwb2lzc29uIHdpdGggYSBsb2cgbGluayBhbmQgb25lIGdhdXNzaWFuIHdpdGggYSBsb2cgbGluay4gCgpgYGB7ciBnbG1zfQoKbW9kX2dsbSA8LSBnbG0oc3VpY2lkZXMgfiBsb2codW5lbXBsb3ltZW50X3JhdGUpICsgbWVkaWFuX2luY29tZSArIGxpdmluZ19zY29yZSArIHdvcnRod2hpbGUgKyBsb2codW5lbXBsb3ltZW50X3JhdGUpKm1lZGlhbl9pbmNvbWUsIGRhdGEgPSBzdWljaWRlc19jb21wbGV0ZSwgZmFtaWx5ID0gZ2F1c3NpYW4obGluaz0ibG9nIiksIG9mZnNldCA9IGxvZ19vcykKCgptb2RfZ2xtMiA8LSBnbG0oc3VpY2lkZXMgfiBsb2codW5lbXBsb3ltZW50X3JhdGUpICsgbWVkaWFuX2luY29tZSArIGxpdmluZ19zY29yZSArIHdvcnRod2hpbGUgKyBsb2codW5lbXBsb3ltZW50X3JhdGUpKm1lZGlhbl9pbmNvbWUsIGRhdGEgPSBzdWljaWRlc19jb21wbGV0ZSwgZmFtaWx5ID0gcG9pc3NvbihsaW5rPSJsb2ciKSwgb2Zmc2V0ID0gbG9nX29zKQoKQUlDKG1vZF9nbG0sbW9kX2dsbTIpCgpgYGAKRml0dGluZyB3aXRoIHRoZXNlIGdlbmVyYWxpc2VkIGxpbmVhciBtb2RlbHMgc2hvd3Mgbm90YWJsZSBpbXByb3ZlbWVudCB0byBvdXIgUi1zcXVhcmVkIHZhbHVlIHRvIDAuODEwIHVuZGVyIHRoZSBnYXVzc2lhbiBtb2RlbCBhbmQgMC44MDYgdW5kZXIgdGhlIHBvaXNzb24gbW9kZWwuIEluIG9yZGVyIHRvIGRldGVybWluZSB3aGljaCBvbmUgdG8gaW5jbHVkZSBpbiBvdXIgZmluYWwgbW9kZWwsIHdlIGNvbnNpZGVyIHRoZSBBSUMgb2YgZWFjaCBtb2RlbCB3aGljaCBpcyBzZWVuIHRvIGJlIDE4MTIuNjEJdW5kZXIgdGhlIGdhdXNzaWFuIG1vZGVsIGFuZCAxNzY5Ljk1IHVuZGVyIHRoZSBwb2lzc29uIG1vZGVsLiBUaGUgcG9pc3NvbiBtb2RlbCB0aHVzIG1pbmltaXNlcyB0aGUgQUlDIGNvbnNpZGVyYWJseSBhbmQgc28gb3VyIGZpbmFsIGFuZCBiZXN0IGZpdHRlZCBtb2RlbCBjYW4gYmUgc3R1ZGllZCBieSB0aGUgc3VtbWFyeSBvdXRwdXQgYmVsb3cgKCopLiBUaGlzIGNsb3NlbHkgZm9sbG93cyB0aGUgcG9pbnQgd2UgbWFkZSBwcmV2aW91c2x5IHJlZ2FyZGluZyB0aGUgaGV0ZXJvc2tlZGFzdGljaXR5IGFuZCB0aHVzIG5vbi1jb25zdGFudCB2YXJpYW5jZSBvZiB0aGUgZGF0YS4gSW4gcGFydGljdWxhciwgd2Uga25vdyB0aGF0IGZvciBhIHBvaXNzb24gZGlzdHJpYnV0aW9uIHZhcmlhbmNlIGluY3JlYXNlcyBhcyBtZWFuIGluY3JlYXNlcyBhbmQgc28gdGhlIHVzZSBvZiB0aGlzIGRpc3RyaWJ1dGlvbiBpcyBjbGVhcmx5IHRoZSBiZXN0IGNob2ljZS4gRmluYWxseSwgbm90ZSBob3cgdGhlIGNvcnJlc3BvbmRpbmcgcC12YWx1ZXMgZm9yIGVhY2ggdGVybSwgZXhjZXB0IHRoYW4gd29ydGh3aGlsZSwgaXMgbGVzcyB0aGFuIDAuMDUsIGltcGx5aW5nIHRoYXQgdGhvc2UgdGVybXMgaXMgc2lnbmlmaWNhbnQgaGVyZS4gQWdhaW4sIHdlIHJlaXRlcmF0ZSB0aGUgZGVjaXNpb24gdG8gcmV0YWluIHRoZSB3b3J0aHdoaWxlIHRlcm0gaXMgZm9yIGVhc2Ugb2YgaW50ZXJwcmV0YXRpb24gYW5kIHdlIHdpbGwgZGlzY3VzcyBwb3NzaWJsZSByZWFzb25zIHdoeSB0aGlzIHRlcm0gZW5kcyB1cCBiZWluZyBpbnNpZ25pZmljYW50LgoKYGBge3Igc3VtbWFyeTIsIHJlc3VsdHM9J2hpZGUnfQpzdW1tYXJ5KG1vZF9nbG0yKQoKYGBgCgoKYGBge3IgZGF0YX0KCmRhdGFfcmVzaWQ8LSBzdWljaWRlc19jb21wbGV0ZSAlPiUgZ2F0aGVyX3Jlc2lkdWFscyhpbml0aWFsX21vZGVsLG1vZF8xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlc2lkID0gInJlc2lkdWFscyIpCgpkYXRhX2Z2PC0gc3VpY2lkZXNfY29tcGxldGUgJT4lIGdhdGhlcl9wcmVkaWN0aW9ucyhpbml0aWFsX21vZGVsLG1vZF8xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucHJlZCA9ImZpdHRlZF92YWxzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJyZXNwb25zZSIpCgpkYXRhX21vZGVscyA8LSBkYXRhX2Z2ICU+JSBsZWZ0X2pvaW4oZGF0YV9yZXNpZCkKCmBgYAoKYGBge3IgcGxzLCBldmFsPUZBTFNFfQoKbG1fZml0dGVkX3Bsb3RzPC1kYXRhX21vZGVscyAlPiUgCiAgICBnZ3Bsb3QoYWVzKHN1aWNpZGVzLCBmaXR0ZWRfdmFscykpICsgCiAgICAgIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKCkrCiAgICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IDEsCiAgICAgICAgICAgICAgICAgICAgY29sID0gInJlZCIpICtmYWNldF93cmFwKH5tb2RlbCwgbnJvdz0yKQogCgpsbV9yZXNpZF9wbG90cyA8LSBkYXRhX21vZGVscyAgJT4lCiAgICAgZ2dwbG90KGFlcyhmaXR0ZWRfdmFscywgcmVzaWR1YWxzKSkgKyAKICAgICBnZW9tX3BvaW50KCkgKwogICAgIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIAogICAgICAgICAgICAgICAgIHNsb3BlID0gMCwgCiAgICAgICAgICAgICAgICAgY29sID0gInJlZCIpICArIAogICAgIGdlb21fc21vb3RoKCkgK2ZhY2V0X3dyYXAofm1vZGVsLCBucm93PTIpCgpsbV9maXR0ZWRfcGxvdHMrbG1fcmVzaWRfcGxvdHMKCmBgYAoKYGBge3IgbG9nfQpnbG1fdHJhbnNfbW9kZWxzIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICAgICBzcHJlYWRfcHJlZGljdGlvbnMobW9kXzIsbW9kXzMsbW9kXzNhLG1vZF9nbG0sbW9kX2dsbTIsCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9InJlc3BvbnNlIikgJT4lIAogICAgIG11dGF0ZShtb2RfMiA9IGV4cChtb2RfMiksbW9kXzMgPSBleHAobW9kXzMpLG1vZF8zYSA9IGV4cChtb2RfM2EpKSAlPiUgCiAgICAgcGl2b3RfbG9uZ2VyKGMoIm1vZF8yIiwibW9kXzMiLCJtb2RfM2EiLCJtb2RfZ2xtIiwibW9kX2dsbTIiKSwKICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibW9kZWwiLAogICAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiZml0dGVkX3ZhbHMiKSAlPiUgCiAgICAgbXV0YXRlKHJlc2lkdWFscyA9IHN1aWNpZGVzIC0gZml0dGVkX3ZhbHMpCgpnbG1fdHJhbnNfZnY8LSBnbG1fdHJhbnNfbW9kZWxzICU+JQogICAgZ2dwbG90KGFlcyhzdWljaWRlcywgZml0dGVkX3ZhbHMpKSArIAogICAgICBnZW9tX3BvaW50KCkgKyAKICAgICAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLAogICAgICAgICAgICAgICAgICAgIHNsb3BlID0gMSwKICAgICAgICAgICAgICAgICAgICBjb2wgPSAicmVkIikrCiAgZ2VvbV9zbW9vdGgoKSArZmFjZXRfd3JhcCh+bW9kZWwsIG5yb3c9MikKICAgICAgICAgCgpmaXRfdnNfcmVzX2dsbTwtZ2xtX3RyYW5zX21vZGVscyAlPiUKICAgICBnZ3Bsb3QoYWVzKGZpdHRlZF92YWxzLCByZXNpZHVhbHMpKSArIAogICAgIGdlb21fcG9pbnQoKSArCiAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgCiAgICAgICAgICAgICAgICAgc2xvcGUgPSAwLCAKICAgICAgICAgICAgICAgICBjb2wgPSAicmVkIikgICsgCiAgZ2VvbV9zbW9vdGgoKSArCiAgICAgIGZhY2V0X3dyYXAofm1vZGVsLCBucm93PTIpCgpnbG1fdHJhbnNfZnYrZml0X3ZzX3Jlc19nbG0KYGBgCgpGaWd1cmUgNzogQWN0dWFsIHZzIEZpdHRlZCAobGVmdCkgYW5kIEZpdHRlZCB2cyBSZXNpZHVhbHMgKFJpZ2h0KSBmb3IgVHJhbnNmb3JtZWQgYW5kIEdMTSBNb2RlbHMKCmBgYHtyIHIyLCByZXN1bHRzPSdoaWRlJ30KZGF0YV9mdiAlPiUgCiAgZ3JvdXBfYnkobW9kZWwpICU+JSAKICAgIHN1bW1hcmlzZShSMiA9IGNvcihzdWljaWRlcyxmaXR0ZWRfdmFscyleMikgJT4lIAogICAgICBrYWJsZShkaWdpdHM9MykgJT4lIAogICAgICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQoKZ2xtX3RyYW5zX21vZGVscyAlPiUgCiAgZ3JvdXBfYnkobW9kZWwpICU+JSAKICAgIHN1bW1hcmlzZShSMiA9IGNvcihzdWljaWRlcyxmaXR0ZWRfdmFscyleMikgJT4lIAogICAgICBrYWJsZShkaWdpdHM9MykgJT4lIAogICAgICAgIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKSAKYGBgCgpXaXRoIHJlZ2FyZHMgdG8gdGhlIHJlc2lkdWFsIHBsb3RzLCBub3RlIGhvdyB0aGUgbW9kZWwgYnVpbGRpbmcgcHJvY2VzcyB1cCB0byB0aGUgZmluYWwgcG9pc3NvbiBtb2RlbCBzbG93bHkgcmVkdWNlcyB0aGUgZWZmZWN0IG9mIGhldGVyb3NrZWRhc3RpY2l0eS4gRm9yIGVhc2llciB2aXN1YWxpc2F0aW9uIHdlIGNhbiByZWZlciB0byB0aGUgUGVhcnNvbnMgcmVzaWR1YWxzIGNvcnJlc3BvbmRpbmcgdG8gb3VyIGZpbmFsIG1vZGVsIGFzIHNlZW4gYmVsb3cgYW5kIG9ic2VydmUgdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBub3cgZXZlbmx5IGRpc3RyaWJ1dGVkIGFib3V0IHRoZSB6ZXJvIHJlZmVyZW5jZSBsaW5lICgqKS4gV2hlbiB0aGUgZml0dGVkIHZhbHVlcyBleGNlZWQgNzUgdGhlcmUgaXMgb3ZlcmVzdGltYXRpb24gb2Ygc3VpY2lkZXMsIHRoaXMgb2Ygd2hpY2ggaXMgbmVnbGlnaWJsZSBhcyB0aGVyZSBpcyBvbmx5IG9uZSBwb2ludCBhYm92ZSB0aGF0IHJhbmdlLgoKYGBge3IsIGZpZy5zaG93PSdoaWRlJywgcmVzdWx0cz0naGlkZScgfQpwZXJzb25zX2ZpbmFsIDwtIHJlc2lkdWFsUGxvdChtb2RfZ2xtMiwgdmFyaWFibGUgPSAiZml0dGVkIiwgdHlwZSA9ICJwZWFyc29uIiwKICAgICAgICAgICAgICBwbG90ID0gVFJVRSwgcXVhZHJhdGljID0gRkFMU0UsIHNtb290aD1UUlVFLCBtYWluID0gIlBlYXJzb24gUmVzaWR1YWwgUGxvdCBmb3IgRmluYWwgTW9kZWwiKQpgYGAKCgpgYGB7ciwgZXZhbD1GQUxTRX0KCmZpbmFsX3ByZWQgPC0gc3VpY2lkZXNfY29tcGxldGUgJT4lIAogIHNwcmVhZF9wcmVkaWN0aW9ucyhtb2RfZ2xtMiwKICAgICAgICAgICAgICAgICAgICAgdHlwZT0icmVzcG9uc2UiKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoIm1vZF9nbG0yIiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm1vZGVsIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImZpdHRlZF92YWxzIikgJT4lIAogIG11dGF0ZShyZXNpZHVhbHMgPSBzdWljaWRlcyAtIGZpdHRlZF92YWxzKQoKCmxpdmluZ19maXQgPC0gc3VpY2lkZXNfY29tcGxldGUlPiUKICBnZ3Bsb3QoYWVzKHggPSBsaXZpbmdfc2NvcmUsIHkgPSBzdWljaWRlcykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKGRhdGEgPSBmaW5hbF9wcmVkLCBhZXMoeT1yb3VuZChmaXR0ZWRfdmFscywwKSksIG1ldGhvZCA9ICJnbG0iLCBtZXRob2QuYXJncyA9IGxpc3QoZmFtaWx5ID0gcG9pc3NvbihsaW5rPSJsb2ciKSksIHNlID0gVFJVRSkrIHlsYWIoInN1aWNpZGVzIHBlciAxMDBLIikKCnVyX2ZpdCA8LSBzdWljaWRlc19jb21wbGV0ZSU+JQogIGdncGxvdChhZXMoeCA9IHVuZW1wbG95bWVudF9yYXRlLCB5ID0gc3VpY2lkZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChkYXRhID0gZmluYWxfcHJlZCwgYWVzKHk9cm91bmQoZml0dGVkX3ZhbHMsMCkpLCBtZXRob2QgPSAiZ2xtIiwgbWV0aG9kLmFyZ3MgPSBsaXN0KGZhbWlseSA9IHBvaXNzb24obGluaz0ibG9nIikpLCBzZSA9IFRSVUUpKyB5bGFiKCJzdWljaWRlcyBwZXIgMTAwSyIpCgptaV9maXQgPC0gc3VpY2lkZXNfY29tcGxldGUlPiUKICBnZ3Bsb3QoYWVzKHggPSBtZWRpYW5faW5jb21lLCB5ID0gc3VpY2lkZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChkYXRhID0gZmluYWxfcHJlZCwgYWVzKHk9cm91bmQoZml0dGVkX3ZhbHMsMCkpLCBtZXRob2QgPSAiZ2xtIiwgbWV0aG9kLmFyZ3MgPSBsaXN0KGZhbWlseSA9IHBvaXNzb24obGluaz0ibG9nIikpLCBzZSA9IFRSVUUpKyB5bGFiKCJzdWljaWRlcyBwZXIgMTAwSyIpCgp3d19maXQgPC0gc3VpY2lkZXNfY29tcGxldGUlPiUKICBnZ3Bsb3QoYWVzKHggPSB3b3J0aHdoaWxlLCB5ID0gc3VpY2lkZXMpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChkYXRhID0gZmluYWxfcHJlZCwgYWVzKHk9cm91bmQoZml0dGVkX3ZhbHMsMCkpLCBtZXRob2QgPSAiZ2xtIiwgbWV0aG9kLmFyZ3MgPSBsaXN0KGZhbWlseSA9IHBvaXNzb24obGluaz0ibG9nIikpLCBzZSA9IFRSVUUpICsgeWxhYigic3VpY2lkZXMgcGVyIDEwMEsiKQoKCgoobGl2aW5nX2ZpdCB8IHVyX2ZpdCkvKG1pX2ZpdCB8IHd3X2ZpdCkKCmBgYAoKRnJvbSBmaWd1cmUgMSBmcm9tIHNlY3Rpb24gQSB3ZSBrbm93IHRoYXQgc3VpY2lkZXMgaW5jcmVhc2Ugd2l0aCBpbmNyZWFzaW5nIGxldmVscyBvZiB1bmVtcGxveW1lbnQgYW5kIGRlcHJpdmF0aW9uIGFuZCBkZWNyZWFzZSB3aXRoIGluY3JlYXNpbmcgaW5jb21lIGFuZCB3ZWxsYmVpbmcuIEludHVpdGl2ZWx5IHRoaXMgbWFrZXMgc2Vuc2UsIGhvd2V2ZXIsIHdoZW4gbG9va2luZyBhdCB0aGUgZWZmZWN0IHBsb3RzIGJlbG93IHdlIHNlZSBhIGRpZmZlcmVudCBvdXRjb21lIHRoYW4gZXhwZWN0ZWQuCgpgYGB7ciBzbW9vdGh9CgojcHJlZF9pbnRlcmFjdGlvbjwtIGdncHJlZGljdChtb2RfZ2xtMiwgYygidW5lbXBsb3ltZW50X3JhdGUiLCAibWVkaWFuX2luY29tZSIpKQpwcmVkX3VyIDwtIHBsb3QoRWZmZWN0KCJ1bmVtcGxveW1lbnRfcmF0ZSIsbW9kX2dsbTIpLHlsYWIgPSAic3VpY2lkZXMgcGVyIDEwMEsiKQpwcmVkX2xpdmluZyA8LSBwbG90KEVmZmVjdCgibGl2aW5nX3Njb3JlIixtb2RfZ2xtMikseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCnByZWRfaW5jb21lIDwtIHBsb3QoRWZmZWN0KCJtZWRpYW5faW5jb21lIixtb2RfZ2xtMikseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCnByZWRfd29ydGggPC0gcGxvdChFZmZlY3QoIndvcnRod2hpbGUiLG1vZF9nbG0yKSx5bGFiID0gInN1aWNpZGVzIHBlciAxMDBLIikKCmdyaWQuYXJyYW5nZShwcmVkX2xpdmluZywgcHJlZF93b3J0aCwgcHJlZF91ciwgcHJlZF9pbmNvbWUsIG5jb2w9MiwgbnJvdyA9IDIpCiNwbG90KHByZWRfaW50ZXJhY3Rpb24pCgojdW5lbXBsb3ltZW50IHJhdGUgZG9lc250IG1ha2Ugc2Vuc2UuLi5wb3NzaWJsZSBjb25mb3VuZGluZyBkdWUgdG8gY29ycmVsYXRlZCB2YXJpYWJsZSBtb3N0IGxpa2VseSBtZWRpYW4gaW5jb21lIHNvIHVzZSB3b3J0aCBtb2RlbCB3aXRoIGludGVyYWN0aW9uIGluc3RlYWQKCiMgbGl2aW5nIHNjb3JlIGFsc28gZG9lcyBub3QgbWFrZSBzZW5zZS4uLi5hbHNvIGFmZmVjdGVkIGJ5IGluY29tZSBzbyBjb25mb3VuZGluZwoKYGBgCkZpZ3VyZSA4OiBFZmZlY3QgUGxvdHMKV2Ugc2VlIHRoYXQgc3VpY2lkZSByYXRlcyB0ZW5kIHRvIGRlY3JlYXNlIHdpdGggaW5jcmVhc2luZyB1bmVtcGxveW1lbnQgcmF0ZXMgYW5kIGRlcHJpdmF0aW9uIHdoaWxlIHRoZXkgaW5jcmVhc2Ugd2l0aCBpbmNyZWFzaW5nIHdlbGxiZWluZy4gVGhpcyBpcyBjb21wbGV0ZWx5IG9wcG9zaXRlIHRvIHdoYXQgd2Ugc2F3IGluIHRoZSBmaXR0ZWQgY3VydmVzIGFuZCBnb2VzIGFnYWluc3Qgb3VyIGludHVpdGlvbiBidXQgd2Uga25vdyB0aGF0IHRoZSBlZmZlY3QgcGxvdHMgYWxsb3cgZm9yIGludmVzdGlnYXRpb24gb2YgaW5kaXZpZHVhbCB2YXJpYWJsZSAobWFyZ2luYWwpIGVmZmVjdHMgd2hpbGUgaG9sZGluZyBvdGhlciBleHBsYW5hdG9yeSB2YXJpYWJsZXMgY29uc3RhbnQuIFRoZXJlZm9yZSwgdGhlIHJlYXNvbiBmb3IgdGhpcyBkaWZmZXJlbmNlIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byB0aGUgcHJlc2VuY2Ugb2YgYSBjb25mb3VuZGluZyB2YXJpYWJsZS4gQXMgd2UgcHJldmlvdXNseSBtZW50aW9uZWQsIG1lZGlhbl9pbmNvbWUgYW5kIHVuZW1wbG95bWVudF9yYXRlIGFyZSBtb2RlcmF0ZWx5IGNvcnJlbGF0ZWQsIHBvc3NpYmx5IHRvIHRoZSBwb2ludCB3aGVyZSB0aGlzIGluY3JlYXNlIGluIHVuZW1wbG95bWVudF9yYXRlIHNlZW4gaW4gZmlndXJlIDEgaXMgYWN0dWFsbHkgZHVlIHRvIHRoZSBwcmVzZW5jZSBvZiB0aGUgdmFyaWFibGUgaW4gb3VyIG1vZGVsLiBJbiBwYXJ0aWN1bGFyLCB3ZSBrbm93IHRoYXQgYXMgdGhlIHVuZW1wbG95bWVudCByYXRlIGRlY2xpbmVzLCBwZXJzb25zIGZlZWwgbGVzcyBzdWljaWRhbCAocG9zaXRpdmUgcmVsYXRpb25zaGlwKSwgaG93ZXZlciB3ZSBhbHNvIGtub3cgdGhhdCBhcyBhIHBlcnNvbidzIHNhbGFyeS9pbmNvbWUgZGVjcmVhc2VzLCB1bmVtcGxveW1lbnQgcmF0ZSB3aWxsIGluY3JlYXNlIGFuZCB0aGVuIHRoZXkgYmVjb21lIG1vcmUgc3VzY2VwdGlibGUgdG8gc3VpY2lkYWwgdGhvdWdodHMuIENsb3NlbHkgcmVsYXRlZCB0byB0aGlzIGlzIHRoZSBmYWN0IHRoYXQgbGVzcyBkZXByaXZhdGlvbiBzaG91bGQgcmVzdWx0IGluIGxlc3Mgc3VpY2lkZXMsIGJ1dCBsZXNzIGluY29tZSBhcyBhIHJlc3VsdCBvZiBsZXNzIGVtcGxveW1lbnQgbWVhbnMgYW4gaW5jcmVhc2UgaW4gZGVwcml2YXRpb24sIHJlc3VsdGluZyBpbiBtb3JlIHN1aWNpZGFsIHRob3VnaHRzLiBMaWtld2lzZSwgaW5jcmVhc2VkIHBlcnNvbmFsIHdlbGxiZWluZyBzaG91bGQgcmVzdWx0IGluIGxlc3Mgc3VpY2lkZXMsIGJ1dCBtb3JlIGxlc3MgYXMgYSByZXN1bHQgb2YgbGVzcyBlbXBsb3ltZW50IGluY29tZSBtZWFucyBhIGRlY3JlYXNlIGluIHdlbGxiZWluZywgcmVzdWx0aW5nIGluIG1vcmUgc3VpY2lkYWwgdGhvdWdodHMuV2UgcmVtb3ZlIHRlcm1zIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGNvbmZvdW5kaW5nIHZhcmlhYmxlIGFuZCBmaXQgYSByZXZpc2VkIGZpbmFsIG1vZGVsIGFzIGZvbGxvd3M6CgpgYGB7cn0KbW9kX2ZpbmFsIDwtIGdsbShzdWljaWRlcyB+IGxvZyh1bmVtcGxveW1lbnRfcmF0ZSkgKyB3b3J0aHdoaWxlICsgbGl2aW5nX3Njb3JlLCBkYXRhID0gc3VpY2lkZXNfY29tcGxldGUsIGZhbWlseSA9IHBvaXNzb24obGluaz0ibG9nIiksIG9mZnNldCA9IGxvZ19vcykKCnByZWRfdXIyIDwtIHBsb3QoRWZmZWN0KCJ1bmVtcGxveW1lbnRfcmF0ZSIsbW9kX2ZpbmFsICkseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCnByZWRfbGl2aW5nMiA8LSBwbG90KEVmZmVjdCgibGl2aW5nX3Njb3JlIixtb2RfZmluYWwgKSx5bGFiID0gInN1aWNpZGVzIHBlciAxMDBLIikKcHJlZF93b3J0aDIgPC0gcGxvdChFZmZlY3QoIndvcnRod2hpbGUiLG1vZF9maW5hbCApLHlsYWIgPSAic3VpY2lkZXMgcGVyIDEwMEsiKQoKCiNncmlkLmFycmFuZ2UocHJlZF9saXZpbmcyLCBwcmVkX3dvcnRoMiwgcHJlZF91cjIsIG5jb2w9MiwgbnJvdyA9IDIpCmBgYApgYGB7cn0KdGlkeShtb2RfZmluYWwpICU+JSAKICBrYWJsZShkaWdpdHMgPSA1LCAKICAgICAgICBjYXB0aW9uID0gIkZpbmFsIFJldmlzZWQgTW9kZWw6IEVzdGltYXRlZCBQYXJhbWV0ZXJzIHdpdGggTG9nIExpbmsgUG9pc3NvbiBHTE0iKSAgJT4lICAKICAgICAgICAgIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IEYpCmBgYApUaGUgaW50ZXJwcmV0YXRpb24gZm9yIHRoZSB0YWJsZSBhYm92ZSBpcyBhcyBmb2xsb3dzOiBmb3IgZWFjaCBleHRyYSB1bml0IHRoYXQgdW5lbXBsb3ltZW50IHJhdGUgaW5jcmVhc2VzIGJ5LCB3ZSBleHBlY3QgdG8gc2VlIGEgcmVsYXRpdmUgaW5jcmVhc2Ugb2YgYWJvdXQgMTAuNSUgKGV4cCgwLjA5OTU4KS0xICRcYXBwcm94JCAwLjEwNDcwNjgpIGluIHRoZSBhdmVyYWdlIG51bWJlciBvZiBzdWljaWRlcyBwZXIgMTAwSyBwZW9wbGUuIExpa2V3aXNlLCB0aGUgYXZlcmFnZSBudW1iZXIgb2Ygc3VpY2lkZXMgZG91YmxlIGZvciBldmVyeSBsb2coMikvKDAuMDk5NTgpICRcYXBwcm94JCA2Ljk2IHVuaXQgaW5jcmVhc2UgaW4gdW5lbXBsb3ltZW50IHJhdGUuIEZyb20gdGhpcyB3ZSBhcmUgdG9sZCB0byBleHBlY3QgYSByZWxhdGl2ZSBpbmNyZWFzZSBvZiBhYm91dCAyNiUgaW4gdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHN1aWNpZGVzIHBlciAxMDBLIHBlb3BsZSB3aXRoIGV2ZXJ5IGluY3JlYXNlIGluIHdvcnRod2hpbGUgZWZmZWN0cyBhbmQgYSByZWxhdGl2ZSBkZWNyZWFzZSBvZiBhYm91dCAwLjIyJSBpbiB0aGUgYXZlcmFnZSBudW1iZXIgb2Ygc3VpY2lkZXMgcGVyIDEwMEsgcGVvcGxlIHdpdGggZXZlcnkgaW5jcmVhc2UgaW4gbGl2aW5nX3Njb3JlOyB3ZSBrbm93IHRoZXNlIGluZmVyZW5jZXMgYXJlIG1pc2xlYWRpbmcgc28gd2UgZGlzcmVnYXJkIHRoZW0uCgpUaGlzIGltcHJvdmVzIG9uIHRoZSB1bmVtcGxveW1lbnRfcmF0ZSBlZmZlY3QgYnV0IHRoZSBsaXZpbmdfc2NvcmUgYW5kIHdvcnRod2hpbGUgZWZmZWN0cyByZW1haW4gdGhlIHNhbWUsIHBvc3NpYmx5IGluZGljYXRpbmcgdGhhdCBhbiB1bmRlcmx5aW5nIGZhY3RvciBpcyByZXNwb25zaWJsZSBmb3Igc3VjaCBkaXNwYXJpdHkuIEluIHBhcnRpY3VsYXIsIHdlIGtub3cgdGhhdCBsaXZpbmcgZGVwcml2YXRpb24sIHBlcnNvbmFsIHdlbGxiZWluZyBhbmQgdW5lbXBsb3ltZW50IHVzdWFsbHkgZ28gaGFuZCBpbiBoYW5kLCBhcyB3ZWxsIGFzIHRoZSBmYWN0IHRoYXQgZGVwcml2YXRpb24gaXMgc3Ryb25nbHkgaW5mbHVlbmNlZCBieSBlbnZpcm9ubWVudGFsIGZhY3RvcnMuIEFub3RoZXIgd2F5IHRvIHRoaW5rIGFib3V0IGl0IGlzIHRoYXQgdW5lbXBsb3llZCBwZXJzb25zIG1heSBub3QgYmUgYWJsZSB0byBhZmZvcmQgdG8gbGl2ZSBpbiAnYmV0dGVyJyBlbnZpcm9ubWVudHMgZHVlIHRvIGxhY2sgb2YgaW5jb21lLCB0aGlzIG9mIHdoaWNoIGFmZmVjdHMgdGhlaXIgd2VsbGJlaW5nLiBXaXRoIHRoaXMgaW4gbWluZCwgd2UgaW52ZXN0aWdhdGUgdGhlIGVmZmVjdHMgb2YgcmVnaW9uYWwgZGlmZmVyZW5jZXMgaW4gdGhlIGZvbGxvd2luZyBzZWN0aW9uIGluIGhvcGVzIG9mIGltcHJvdmluZyBvdXIgbW9kZWwuCgoKIyMgICBRMi4gV2hhdCBhcmUgdGhlIHJlZ2lvbmFsIGRpZmZlcmVuY2VzIGluIHRoZSBudW1iZXIgb2Ygc3VpY2lkZXMgaW4gRW5nbGFuZD8KYGBge3IsIGV2YWw9RkFMU0V9CnJlZ19pbnQwIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICAgICBnZ3Bsb3QoYWVzKHggPSB1bmVtcGxveW1lbnRfcmF0ZSwKICAgICAgICAgICAgICAgIHkgPSBzdWljaWRlX3JhdGUsY29sb3IgPSByZWdpb24pKSArCiAgICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHkgfiBwb2x5KHgsMSksIG1ldGhvZCA9IGxtLCBzZT1GKSArIHNjYWxlX3hfY29udGludW91cyh0cmFucz0ibG9nIikKcmVnX2ludDEgPC0gc3VpY2lkZXNfY29tcGxldGUgJT4lIAogICAgIGdncGxvdChhZXMoeCA9IGxpdmluZ19zY29yZSwKICAgICAgICAgICAgICAgIHkgPSBzdWljaWRlX3JhdGUsY29sb3IgPSByZWdpb24pKSArCiAgICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHkgfiBwb2x5KHgsMSksIG1ldGhvZCA9IGxtLCBzZT1GKQpncmlkLmFycmFuZ2UocmVnX2ludDAscmVnX2ludDEsbmNvbD0xKQoKI2ludGVyYWN0aW9uIHRha2luZyBwbGFjZQpgYGAKCkZyb20gdGhlIGFib3ZlIHBsb3QgKCopLCB3ZSBjYW4gc2VlIHRoYXQgaW50ZXJhY3Rpb24gaXMgdGFraW5nIHBsYWNlIGJldHdlZW4gdGhlIGRpZmZlcmVudCByZWdpb25zIGFuZCBzbyB3ZSBpbXBsZW1lbnQgdGhpcyBpbiBvdXIgcmV2aXNlZCBtb2RlbCBiZWxvdy4KQ29uZHVjdGluZyBhbiBBTk9WQSBjb25maXJtcyB0aGF0IHRoZSBsb2codW5lbXBsb3ltZW50X3JhdGUpICogcmVnaW9uIGFuZCBsaXZpbmdfc2NvcmUgKiByZWdpb24gdGVybXMgYXJlIHNpZ25pZmljYW50ICgqKS4KCmBgYHtyIHJlZ2lvbiwgcmVzdWx0cz0naGlkZSd9Cgptb2RfcmVnXzAgPC0gZ2xtKHN1aWNpZGVzIH4gbG9nKHVuZW1wbG95bWVudF9yYXRlKSArIGxpdmluZ19zY29yZSArIHdvcnRod2hpbGUgLCBkYXRhID0gc3VpY2lkZXNfY29tcGxldGUsIGZhbWlseSA9IHBvaXNzb24obGluaz0ibG9nIiksIG9mZnNldCA9IGxvZ19vcykKCm1vZF9yZWdfZmluYWwgPC0gZ2xtKHN1aWNpZGVzIH4gbG9nKHVuZW1wbG95bWVudF9yYXRlKSpyZWdpb24gKyB3b3J0aHdoaWxlICsgcmVnaW9uKmxpdmluZ19zY29yZSwgZGF0YSA9IHN1aWNpZGVzX2NvbXBsZXRlLCBmYW1pbHkgPSBwb2lzc29uKGxpbms9ImxvZyIpLCBvZmZzZXQgPSBsb2dfb3MpCgoKYW5vdmEobW9kX3JlZ18wICxtb2RfcmVnX2ZpbmFsLHRlc3Q9IkxSVCIpICMgcCB2YWx1ZSBsZXNzIHRoYW4gMC4wNSA+IGludGVyYWN0aW9uIHNpZ25pZmljYW50CgpgYGAKCgpgYGB7ciBlZmZlY3QxLGZpZy5kaW0gPSBjKDgsIDQpLGV2YWw9VFJVRX0KcHJlZF91cjMgPC0gcGxvdChFZmZlY3QoInVuZW1wbG95bWVudF9yYXRlIixtb2RfcmVnX2ZpbmFsICkpCnByZWRfbGl2aW5nMyA8LSBwbG90KEVmZmVjdCgibGl2aW5nX3Njb3JlIixtb2RfcmVnX2ZpbmFsICkpCnByZWRfd29ydGgzIDwtIHBsb3QoRWZmZWN0KCJ3b3J0aHdoaWxlIixtb2RfcmVnX2ZpbmFsICkpCnByZWRfZ2d1cjwtIGdncHJlZGljdChtb2RfcmVnX2ZpbmFsLCBjKCJ1bmVtcGxveW1lbnRfcmF0ZSIpKQpwcmVkX2dnbHM8LSBnZ3ByZWRpY3QobW9kX3JlZ19maW5hbCwgYygibGl2aW5nX3Njb3JlIikpCnByZWRfZ2d3dzwtIGdncHJlZGljdChtb2RfcmVnX2ZpbmFsLCBjKCJ3b3J0aHdoaWxlIikpCgpwYXIobWZyb3cgPSBjKDEsIDIpKQojcGxvdChwcmVkX2dndXIpCnBsb3QocHJlZF9nZ2xzKSAKcGxvdChwcmVkX2dnd3cpCmBgYAoKCldlIG5vdyBzZWUgYSBtb3JlIHNlbnNpYmxlIHJlc3VsdCBmb3IgdGhlIG1hcmdpbmFsIGVmZmVjdCBvZiBsaXZpbmdfc2NvcmUgYXBwZWFycyB0byBiZSBwb3NpdGl2ZSBpbiByZWxhdGlvbiB0byBzdWljaWRlIGNvdW50cy4gQ29udmVyc2VseSwgd2Ugc3RpbGwgc2VlIG5vIGltcHJvdmVtZW50IHRvIHRoZSB3b3J0aHdoaWxlIHBsb3QuIFRoaXMgbWF5IGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSByYW5nZSBwcm92aWRlZCBmb3IgdGhlIHNhbXBsZWQgd29ydGh3aGlsZSB2YWx1ZXMgcHJvdmVzIHRvIGJlIHZlcnkgc21hbGwgYW5kIHRodXMgaXMgbm90IGFibGUgdG8gY29uZmVyIGFueSBzaWduaWZpY2FudCBlZmZlY3RzIGluIHRoaXMgY2FzZS4KCkZyb20gdGhlIHBsb3QgYmVsb3cgd2UgY2FuIHNlZSB0aGF0IGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBlZmZlY3Qgb2YgZGlmZmVyZW50IHJlZ2lvbnMgb24gc3VpY2lkZSByYXRlIGFjdHVhbGx5IGRlcGVuZHMgb24gdGhlIHVuZGVybHlpbmcgYXNzdW1lZCB1bmVtcGxveW1lbnQgcmF0ZXMgYW5kIGxpdmluZyBzY29yZXMuIEhvd2V2ZXIsIG5vdGUgdGhhdCB0aGlzIGRpZmZlcmVuY2UgaXMgbm90IHNvIHNpZ25pZmljYW50IGFzIHRoZSBpbnRlcnZhbHMgZm9yIGVhY2ggcmVnaW9uIG92ZXJsYXAgd2l0aCBlYWNoIG90aGVyLgoKYGBge3IgZWZmZWN0LGV2YWw9VFJVRSxmaWcuZGltID0gYygxNiwgOCl9CgoKcmVnX3Bsb3RfMCA8LSBwbG90KEVmZmVjdCgicmVnaW9uIiwKICAgICAgICAgICAgICAgICBtb2RfcmVnX2ZpbmFsKSkKCnJlZ19wbG90XzEgPC0gcGxvdChFZmZlY3QoInJlZ2lvbiIsCiAgICAgICAgICAgICAgICAgbW9kX3JlZ19maW5hbCAsCiAgICAgICAgICAgICAgICAgZml4ZWQucHJlZGljdG9ycyA9IGxpc3QoZ2l2ZW4udmFsdWVzID0gYyhgbG9nKHVuZW1wbG95bWVudF9yYXRlKWA9bG9nKDIpKSkpLCBtYWluID0gInVuZW1wbG95bWVudF9yYXRlIG9mIDIiLHlsYWIgPSAic3VpY2lkZXMgcGVyIDEwMEsiKQpyZWdfcGxvdF8yIDwtICBwbG90KEVmZmVjdCgicmVnaW9uIiwKICAgICAgICAgICAgICAgICBtb2RfcmVnX2ZpbmFsICwKICAgICAgICAgICAgICAgICBmaXhlZC5wcmVkaWN0b3JzID0gbGlzdChnaXZlbi52YWx1ZXMgPSBjKGBsb2codW5lbXBsb3ltZW50X3JhdGUpYD1sb2coNykpKSksIG1haW4gPSAidW5lbXBsb3ltZW50X3JhdGUgb2YgNyIseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCgpyZWdfcGxvdF8zIDwtIHBsb3QoRWZmZWN0KCJyZWdpb24iLAogICAgICAgICAgICAgICAgIG1vZF9yZWdfZmluYWwgLAogICAgICAgICAgICAgICAgIGZpeGVkLnByZWRpY3RvcnMgPSBsaXN0KGdpdmVuLnZhbHVlcyA9IGMoYGxpdmluZ19zY29yZWA9MTApKSksIG1haW4gPSAibGl2aW5nX3Njb3JlIG9mIDEwIix5bGFiID0gInN1aWNpZGVzIHBlciAxMDBLIikKcmVnX3Bsb3RfNCA8LSAgcGxvdChFZmZlY3QoInJlZ2lvbiIsCiAgICAgICAgICAgICAgICAgbW9kX3JlZ19maW5hbCAsCiAgICAgICAgICAgICAgICAgZml4ZWQucHJlZGljdG9ycyA9IGxpc3QoZ2l2ZW4udmFsdWVzID0gYyhgbGl2aW5nX3Njb3JlYD00MCkpKSwgbWFpbiA9ICJsaXZpbmdfc2NvcmUgb2YgNDAiLHlsYWIgPSAic3VpY2lkZXMgcGVyIDEwMEsiKQoKCgoKcmVnX3Bsb3RfMCAKI3JlZ19wbG90XzEgCiNyZWdfcGxvdF8yCiNyZWdfcGxvdF8zIAojcmVnX3Bsb3RfNAoKCiN3b3J0aHdoaWxlIGFuZCBsaXZpbmdfc2NvcmUgaW5zaWduaWZpY2FudC4uLmxpdmluZ19zY29yZSBpbmZsdWVuY2VkIGJ5IGluY29tZSBhbmQgaW5jb21lIGluZmx1ZW5jZWQgYnkgdW5lbXBsb3ltZW50IHJhdGUKIyB0byBzZWUgZWZmZWN0IG9mIHJlZ2lvbnMgd2UgaGF2ZSB0byB2YXJ5IHRoZSB1bmVtcGxveW1lbnQgdmFyaWFibGUKIyB1bmVtcGxveW1lbnQgc2VlbXMgdG8gaGF2ZSBtb3JlIGluZmx1ZW5jZSBvbiBzdWljaWRlcyBjb21wYXJlZCB0byBsaXZpbmcgc2NvcmUgKHBpbmsgaW50ZXJ2YWxzKQojbm8gc2lnbmlmaWNhbnQgcmVnaW9uYWwgZGlmZmVyZW5jZSBhcyBpbnRlcnZhbHMgaW50ZXJsYXAKCmBgYAoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQp0aWR5KG1vZF9yZWdfZmluYWwpICU+JSAKICBrYWJsZShkaWdpdHMgPSA1LCAKICAgICAgICBjYXB0aW9uID0gIlJlZ2lvbiBNb2RlbDogRXN0aW1hdGVkIFBhcmFtZXRlcnMgd2l0aCBMb2cgTGluayBQb2lzc29uIEdMTSIpICAlPiUgIAogICAgICAgICAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gRikKYGBgCgojIyBRMy4gQXJlIHRoZXJlIGFueSBkaWZmZXJlbmNlIGluIHN1aWNpZGVzIHdpdGggcmVnYXJkcyB0byB0aGUgTm9ydGgtU291dGggZGl2aWRlPwoKSW4gb3JkZXIgdG8gaW1wbGVtZW50IHRoaXMgYW5hbHlzaXMgd2UgbXVzdCBmaXJzdCBjcmVhdGUgYSBuZXcgY29sdW1uIGluIG91ciBleGlzdGluZy9pbml0aWFsIGRhdGFmcmFtZS4gVG8gZnVydGhlciBjYXRlcmdvcmlzZSB0aGUgcmVnaW9ucyBpbnRvIE5vcnRoIGFuZCBTb3V0aCwgSSByZWZlcnJlZCB0byB0aGlzIChodHRwczovL2dlb2dyYXBoaWNhbC5jby51ay9pbWFnZXMvMjAyMC9Ob3J0aF9Tb3V0aF9kaXZpZGUvTWFwLnBuZykgbWFwLiBGb3IgdGhpcyBxdWVzdGlvbiBJIG9wdGVkIHRvIHJlbW92ZSB0aGUgd29ydGh3aGlsZSB0ZXJtIGZyb20gdGhlIG1vZGVsIGR1ZSB0byByZWFzb25zIGRpc2N1c3NlZCBpbiB0aGUgcHJldmlvdXMgcXVlc3Rpb24uIApgYGB7cn0Kc2V0LnNlZWQoMzU3KQpzdWljaWRlc19jb21wbGV0ZSROX29yX1MgPC0gcmVwKE5BLCBucm93KHN1aWNpZGVzX2NvbXBsZXRlKSkKc3VpY2lkZXNfY29tcGxldGVbc3VpY2lkZXNfY29tcGxldGUkcmVnaW9uID09ICJOb3J0aCBFYXN0IiwgXVssICJOX29yX1MiXSA8LSAiTm9ydGgiCnN1aWNpZGVzX2NvbXBsZXRlW3N1aWNpZGVzX2NvbXBsZXRlJHJlZ2lvbiA9PSAiTm9ydGggV2VzdCIsIF1bLCAiTl9vcl9TIl0gPC0gIk5vcnRoIgpzdWljaWRlc19jb21wbGV0ZVtzdWljaWRlc19jb21wbGV0ZSRyZWdpb24gPT0gIllvcmtzaGlyZSBhbmQgVGhlIEh1bWJlciIsIF1bLCAiTl9vcl9TIl0gPC0gIk5vcnRoIgpzdWljaWRlc19jb21wbGV0ZVtzdWljaWRlc19jb21wbGV0ZSRyZWdpb24gPT0gIkVhc3QgTWlkbGFuZHMiLCBdWywgIk5fb3JfUyJdIDwtICJOb3J0aCIKc3VpY2lkZXNfY29tcGxldGVbc3VpY2lkZXNfY29tcGxldGUkcmVnaW9uID09ICJXZXN0IE1pZGxhbmRzIiwgXVssICJOX29yX1MiXSA8LSAiTm9ydGgiCnN1aWNpZGVzX2NvbXBsZXRlW3N1aWNpZGVzX2NvbXBsZXRlJHJlZ2lvbiA9PSAiRWFzdCBvZiBFbmdsYW5kIiwgXVssICJOX29yX1MiXSA8LSAiU291dGgiCnN1aWNpZGVzX2NvbXBsZXRlW3N1aWNpZGVzX2NvbXBsZXRlJHJlZ2lvbiA9PSAiTG9uZG9uIiwgXVssICJOX29yX1MiXSA8LSAiU291dGgiCnN1aWNpZGVzX2NvbXBsZXRlW3N1aWNpZGVzX2NvbXBsZXRlJHJlZ2lvbiA9PSAiU291dGggV2VzdCIsIF1bLCAiTl9vcl9TIl0gPC0gIlNvdXRoIgpzdWljaWRlc19jb21wbGV0ZVtzdWljaWRlc19jb21wbGV0ZSRyZWdpb24gPT0gIlNvdXRoIEVhc3QiLCBdWywgIk5fb3JfUyJdIDwtICJTb3V0aCIKCm1vZF9OX1MgPC0gZ2xtKHN1aWNpZGVzIH4gTl9vcl9TKmxvZyh1bmVtcGxveW1lbnRfcmF0ZSkgKyBOX29yX1MqbGl2aW5nX3Njb3JlICwgZGF0YSA9IHN1aWNpZGVzX2NvbXBsZXRlLCBmYW1pbHkgPSBwb2lzc29uKGxpbms9ImxvZyIpLCBvZmZzZXQgPSBsb2dfb3MpCgpgYGAKCgoKYGBge3J9Ck5fU19wbG90XzAgPC0gcGxvdChFZmZlY3QoIk5fb3JfUyIsCiAgICAgICAgICAgICAgICAgbW9kX05fUykpCgoKTl9TX3Bsb3RfMSA8LSBwbG90KEVmZmVjdCgiTl9vcl9TIiwKICAgICAgICAgICAgICAgICBtb2RfTl9TICwKICAgICAgICAgICAgICAgICBmaXhlZC5wcmVkaWN0b3JzID0gbGlzdChnaXZlbi52YWx1ZXMgPSBjKGBsb2codW5lbXBsb3ltZW50X3JhdGUpYD1sb2coMikpKSksIG1haW4gPSAidW5lbXBsb3ltZW50X3JhdGUgb2YgMiIseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCk5fU19wbG90XzIgPC0gIHBsb3QoRWZmZWN0KCJOX29yX1MiLAogICAgICAgICAgICAgICAgIG1vZF9OX1MgLAogICAgICAgICAgICAgICAgIGZpeGVkLnByZWRpY3RvcnMgPSBsaXN0KGdpdmVuLnZhbHVlcyA9IGMoYGxvZyh1bmVtcGxveW1lbnRfcmF0ZSlgPWxvZyg3KSkpKSwgbWFpbiA9ICJ1bmVtcGxveW1lbnRfcmF0ZSBvZiA3Iix5bGFiID0gInN1aWNpZGVzIHBlciAxMDBLIikKCk5fU19wbG90XzMgPC0gcGxvdChFZmZlY3QoIk5fb3JfUyIsCiAgICAgICAgICAgICAgICAgbW9kX05fUyAsCiAgICAgICAgICAgICAgICAgZml4ZWQucHJlZGljdG9ycyA9IGxpc3QoZ2l2ZW4udmFsdWVzID0gYyhgbGl2aW5nX3Njb3JlYD0xMCkpKSwgbWFpbiA9ICJsaXZpbmdfc2NvcmUgb2YgMTAiLHlsYWIgPSAic3VpY2lkZXMgcGVyIDEwMEsiKQpOX1NfcGxvdF80IDwtICBwbG90KEVmZmVjdCgiTl9vcl9TIiwKICAgICAgICAgICAgICAgICBtb2RfTl9TICwKICAgICAgICAgICAgICAgICBmaXhlZC5wcmVkaWN0b3JzID0gbGlzdChnaXZlbi52YWx1ZXMgPSBjKGBsaXZpbmdfc2NvcmVgPTQwKSkpLCBtYWluID0gImxpdmluZ19zY29yZSBvZiA0MCIseWxhYiA9ICJzdWljaWRlcyBwZXIgMTAwSyIpCgoKCk5fU19wbG90XzAKI05fU19wbG90XzEgCiNOX1NfcGxvdF8yIAojTl9TX3Bsb3RfMwojTl9TX3Bsb3RfNCAKCiNncmlkLmFycmFuZ2UoTl9TX3Bsb3RfMSxOX1NfcGxvdF8yLE5fU19wbG90XzMsTl9TX3Bsb3RfNCwgIG5jb2w9MiwgbnJvdyA9IDIpCmBgYAoKCmBgYHtyIGxvZzIsIGV2YWw9RkFMU0V9CgpyZWdpb25fbW9kZWxzIDwtIHN1aWNpZGVzX2NvbXBsZXRlICU+JSAKICAgICBzcHJlYWRfcHJlZGljdGlvbnMobW9kX3JlZ18wLG1vZF9yZWdfZmluYWwsbW9kX05fUywKICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0icmVzcG9uc2UiKSAlPiUgCiAgICAgcGl2b3RfbG9uZ2VyKGMoIm1vZF9yZWdfMCIsIm1vZF9yZWdfZmluYWwiLCJtb2RfTl9TIiksCiAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm1vZGVsIiwKICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImZpdHRlZF92YWxzIikgJT4lIAogICAgIG11dGF0ZShyZXNpZHVhbHMgPSBzdWljaWRlcyAtIGZpdHRlZF92YWxzKQoKcmVnaW9uX2Z2PC0gcmVnaW9uX21vZGVscyAlPiUKICAgIGdncGxvdChhZXMoc3VpY2lkZXMsIGZpdHRlZF92YWxzKSkgKyAKICAgICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoKSArCiAgICAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IDEsCiAgICAgICAgICAgICAgICAgICAgY29sID0gInJlZCIpICArCiAgICAgICAgICAgZmFjZXRfd3JhcCh+bW9kZWwpCgpmaXRfdnNfcmVzX3JlZ2lvbjwtcmVnaW9uX21vZGVscyAlPiUKICAgICBnZ3Bsb3QoYWVzKGZpdHRlZF92YWxzLCByZXNpZHVhbHMpKSArIAogICAgIGdlb21fcG9pbnQoKSArCiAgICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgCiAgICAgICAgICAgICAgICAgc2xvcGUgPSAwLCAKICAgICAgICAgICAgICAgICBjb2wgPSAicmVkIikgICsgCiAgICAgZ2VvbV9zbW9vdGgoKSArCiAgICAgZmFjZXRfd3JhcCh+IG1vZGVsLCBucm93ID0gMikgKyAKICAgICBnZ3RpdGxlKCJGaXR0ZWQgcmVzcG9uc2UgdmFsdWVzIHZzIFJlc2lkdWFscyIpCgpyZWdpb25fbW9kZWxzICU+JSAKICBncm91cF9ieShtb2RlbCkgJT4lIAogICAgc3VtbWFyaXNlKFIyID0gY29yKHN1aWNpZGVzLGZpdHRlZF92YWxzKV4yKSAlPiUgCiAgICAgIGthYmxlKGRpZ2l0cz0zKSAlPiUgCiAgICAgICAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UpCgpwZXJzb25zX2ZpbmFsX3JlZyA8LSByZXNpZHVhbFBsb3QobW9kX3JlZ19maW5hbCwgdmFyaWFibGUgPSAiZml0dGVkIiwgdHlwZSA9ICJwZWFyc29uIiwKICAgICAgICAgICAgICBwbG90ID0gVFJVRSwgcXVhZHJhdGljID0gRkFMU0UsIHNtb290aD1UUlVFLCBtYWluID0gIlBlYXJzb24gUmVzaWR1YWwgUGxvdCBmb3IgRmluYWwgUmVnaW9uIE1vZGVsIikKCnJlZ2lvbl9mdgpmaXRfdnNfcmVzX3JlZ2lvbgoKCkFJQyhtb2RfcmVnXzAsbW9kX3JlZ19maW5hbCxtb2RfTl9TKQpgYGAKCgojIFJlZmVyZW5jZXMKCkluY2x1ZGUgeW91ciByZWZlcmVuY2VzIGluIHRoaXMgc2VjdGlvbi4gVGhlIHJlZmVyZW5jZXMgYmVsb3cgYXJlIGV4YW1wbGVzIG9mIGJvb2tzIGFuZCBhIHdlYnNpdGUuCgo8IS0tCkluY2x1ZGUgeW91ciByZWZlcmVuY2VzIGluIHRoaXMgc2VjdGlvbi4gVGhlIHJlZmVyZW5jZXMgYmVsb3cgYXJlIGV4YW1wbGVzIG9mIGJvb2tzIGFuZCBhIHdlYnNpdGUKLS0+CgoxLiAgV2lja2hhbSwgSC4gKmdncGxvdDI6IEVsZWdhbnQgR3JhcGhpY3MgZm9yIERhdGEgQW5hbHlzaXMqIFtvbi1saW5lIHZlcnNpb25dKGh0dHBzOi8vZ2dwbG90Mi1ib29rLm9yZy9pbmRleC5odG1sKQoKCjIuICBXaWNraGFtLCBILiAmIEdyb2xlbXVuZCwgRy4gKlIgZm9yIERhdGEgU2NpZW5jZS4qIFtvbi1saW5lIHZlcnNpb25dKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovaW5kZXguaHRtbCkKCjMuIFtEZXBhcnRtZW50IG9mIE1hdGhzIHdlYnNpdGVdKGh0dHBzOi8vd3d3LmJhdGguYWMudWsvZGVwYXJ0bWVudHMvZGVwYXJ0bWVudC1vZi1tYXRoZW1hdGljYWwtc2NpZW5jZXMvKQo=